/* Returns the status code from PXE (0 on success), or -1 on invocation failure */ int pxe_get_nic_type(t_PXENV_UNDI_GET_NIC_TYPE *gnt) { com32sys_t regs; t_PXENV_UNDI_GET_NIC_TYPE *lgnt; lgnt = lzalloc(sizeof *lgnt); if (!lgnt) return -1; memset(®s, 0, sizeof regs); regs.eax.w[0] = 0x0009; regs.ebx.w[0] = PXENV_UNDI_GET_NIC_TYPE; regs.es = SEG(lgnt); /* regs.edi.w[0] = OFFS(lgnt); */ __intcall(0x22, ®s, ®s); memcpy(gnt, lgnt, sizeof(t_PXENV_UNDI_GET_NIC_TYPE)); lfree(lgnt); if (regs.eflags.l & EFLAGS_CF) return -1; return gnt->Status; }
static void sanboot(const char **args) { char *q; struct s_PXENV_FILE_EXEC *fx; com32sys_t reg; memset(®, 0, sizeof reg); fx = __com32.cs_bounce; q = (char *)(fx+1); fx->Status = 1; fx->Command.offs = OFFS(q); fx->Command.seg = SEG(q); q = stpcpy(q, "sanboot"); while (*args) { *q++ = ' '; q = stpcpy(q, *args); args++; } memset(®, 0, sizeof reg); reg.eax.w[0] = 0x0009; reg.ebx.w[0] = 0x00e5; /* PXENV_FILE_EXEC */ reg.edi.w[0] = OFFS(fx); reg.es = SEG(fx); __intcall(0x22, ®, ®); /* This should not return... */ }
static bool plop_INT13h_check(void) { com32sys_t inregs, outregs; /* Prepare the register set */ memset(&inregs, 0, sizeof inregs); /* * Check if PLoP already has booted a CDROM or USB drive by checking * for the presence of the PLoP INT13h hook. * * The following assembly code (NASM) can detect the PLoP INT13h hook: * * mov eax,'PoLP' ; Reverse of 'PLoP' * mov ebp,'DKHC' ; Reverse of 'CHKD' * int 13h * cmp eax,' sey' ; Reverse of 'yes ' * jz plop_INT13h_active */ inregs.eax.l = 0x504c6f50; /* "PLoP" */ inregs.ebp.l = 0x43484b44; /* "CHKD" */ __intcall(0x13, &inregs, &outregs); /* eax will contain "yes " if PLoP INT13h hook is available */ if (outregs.eax.l == 0x79657320) return true; return false; }
void __ansicon_beep(void) { static com32sys_t ireg; ireg.eax.w[0] = 0x0e07; ireg.ebx.b[1] = BIOS_PAGE; __intcall(0x10, &ireg, NULL); }
int syslinux_adv_write(void) { static com32sys_t reg; reg.eax.w[0] = 0x001d; __intcall(0x22, ®, ®); return (reg.eflags.l & EFLAGS_CF) ? -1 : 0; }
void runsyslinuxcmd(const char *cmd) { strcpy(__com32.cs_bounce, cmd); REG_AX(inreg) = 0x0003; // Run command REG_BX(inreg) = OFFS(__com32.cs_bounce); REG_ES(inreg) = SEG(__com32.cs_bounce); __intcall(0x22, &inreg, &outreg); }
/* Show or hide the cursor */ static void ansicon_showcursor(const struct term_state *st) { static com32sys_t ireg; ireg.eax.b[1] = 0x01; ireg.ecx.w[0] = st->cursor ? cursor_type : 0x2020; __intcall(0x10, &ireg, NULL); }
unsigned int getversion(char *deriv,unsigned int *numfun) { REG_AX(inreg) = 0x0001; __intcall(0x22,&inreg,&outreg); if (deriv) *deriv= REG_DL(outreg); if (numfun) *numfun = REG_AX(outreg); return REG_CX(outreg); }
void syslinux_final_cleanup(uint16_t flags) { static com32sys_t ireg; ireg.eax.w[0] = 0x000c; ireg.edx.w[0] = flags; __intcall(0x22, &ireg, NULL); }
static void emit(char ch) { static com32sys_t ireg; /* Zeroed with the BSS */ ireg.eax.b[1] = 0x04; ireg.edx.b[0] = ch; __intcall(0x21, &ireg, NULL); }
static void __constructor __syslinux_get_shuffer_size(void) { static com32sys_t reg; reg.eax.w[0] = 0x0023; __intcall(0x22, ®, ®); shuffler_size = (reg.eflags.l & EFLAGS_CF) ? 2048 : reg.ecx.w[0]; }
char issyslinux(void) { REG_EAX(inreg) = 0x00003000; REG_EBX(inreg) = REG_ECX(inreg) = REG_EDX(inreg) = 0xFFFFFFFF; __intcall(0x21, &inreg, &outreg); return (REG_EAX(outreg) == 0x59530000) && (REG_EBX(outreg) == 0x4c530000) && (REG_ECX(outreg) == 0x4e490000) && (REG_EDX(outreg) == 0x58550000); }
void OS::cleanup(void) { static com32sys_t rm; rm.eax.w[0] = 0x000C; rm.edx.w[0] = 0x0000; printf("Unloading bootloader stack"); __intcall(0x22, &rm, NULL); printf("\n"); }
static int pxeapi_call(int func, const uint8_t *buf) { static com32sys_t inargs, outargs; inargs.eax.w[0] = 0x0009; /* Call PXE Stack */ inargs.ebx.w[0] = func; /* PXE function number */ inargs.edi.w[0] = OFFS(buf); inargs.es = SEG(buf); __intcall(0x22, &inargs, &outargs); return outargs.eax.w[0] == PXENV_EXIT_SUCCESS; }
void __pci_write_bios(uint32_t call, uint32_t v, pciaddr_t a) { com32sys_t rs; memset(&rs, 0, sizeof rs); rs.eax.w[0] = call; rs.ebx.w[0] = a >> 8; /* bus:device:function */ rs.edi.b[0] = a; /* address:reg */ rs.ecx.l = v; __intcall(0x1a, &rs, NULL); }
static void dump_e820(void) { com32sys_t ireg, oreg; struct e820_data ed; uint32_t type; void *low_ed; low_ed = lmalloc(sizeof ed); if (!low_ed) return; memset(&ireg, 0, sizeof ireg); ireg.eax.w[0] = 0xe820; ireg.edx.l = 0x534d4150; ireg.ecx.l = sizeof(struct e820_data); ireg.edi.w[0] = OFFS(low_ed); ireg.es = SEG(low_ed); memset(&ed, 0, sizeof ed); ed.extattr = 1; do { memcpy(low_ed, &ed, sizeof ed); __intcall(0x15, &ireg, &oreg); if (oreg.eflags.l & EFLAGS_CF || oreg.eax.l != 0x534d4150 || oreg.ecx.l < 20) break; memcpy(&ed, low_ed, sizeof ed); if (oreg.ecx.l >= 24) { /* ebx base length end type */ printf("%8x %016llx %016llx %016llx %d [%x]", ireg.ebx.l, ed.base, ed.len, ed.base + ed.len, ed.type, ed.extattr); } else { /* ebx base length end */ printf("%8x %016llx %016llx %016llx %d [-]", ireg.ebx.l, ed.base, ed.len, ed.base + ed.len, ed.type); ed.extattr = 1; } type = ed.type - 1; if (type < sizeof(e820_types) / sizeof(e820_types[0])) printf(" %s", e820_types[type]); putchar('\n'); ireg.ebx.l = oreg.ebx.l; } while (ireg.ebx.l); lfree(low_ed); }
static int get_disk_params(int disk) { static com32sys_t getparm, parm, getebios, ebios; disk_info.disk = disk; disk_info.ebios = disk_info.cbios = 0; /* Get EBIOS support */ getebios.eax.w[0] = 0x4100; getebios.ebx.w[0] = 0x55aa; getebios.edx.b[0] = disk; getebios.eflags.b[0] = 0x3; /* CF set */ __intcall(0x13, &getebios, &ebios); if ( !(ebios.eflags.l & EFLAGS_CF) && ebios.ebx.w[0] == 0xaa55 && (ebios.ecx.b[0] & 1) ) { disk_info.ebios = 1; } /* Get disk parameters -- really only useful for hard disks, but if we have a partitioned floppy it's actually our best chance... */ getparm.eax.b[1] = 0x08; getparm.edx.b[0] = disk; __intcall(0x13, &getparm, &parm); if ( parm.eflags.l & EFLAGS_CF ) return disk_info.ebios ? 0 : -1; disk_info.head = parm.edx.b[1]+1; disk_info.sect = parm.ecx.b[0] & 0x3f; if ( disk_info.sect == 0 ) { disk_info.sect = 1; } else { disk_info.cbios = 1; /* Valid geometry */ } return 0; }
static void ansicon_scroll_up(const struct term_state *st) { static com32sys_t ireg; ireg.eax.w[0] = 0x0601; ireg.ebx.b[1] = ansicon_attribute(st); ireg.ecx.w[0] = 0; ireg.edx.b[1] = ti.rows-1; ireg.edx.b[0] = ti.cols-1; __intcall(0x10, &ireg, NULL); /* Scroll */ }
void __constructor __syslinux_get_derivative_info(void) { com32sys_t *const r = &__syslinux_derivative_info.rr.r; r->eax.w[0] = 0x000A; __intcall(0x22, r, r); __syslinux_derivative_info.r.esbx = MK_PTR(r->es, r->ebx.w[0]); __syslinux_derivative_info.r.fssi = MK_PTR(r->fs, r->esi.w[0]); __syslinux_derivative_info.r.gsdi = MK_PTR(r->gs, r->edi.w[0]); }
uint32_t __pci_read_bios(uint32_t call, pciaddr_t a) { com32sys_t rs; memset(&rs, 0, sizeof rs); rs.eax.w[0] = call; rs.ebx.w[0] = a >> 8; /* bus:device:function */ rs.edi.b[0] = a; /* address:reg */ __intcall(0x1a, &rs, &rs); return (rs.eflags.l & EFLAGS_CF) ? ~(uint32_t)0 : rs.ecx.l; }
void __constructor __syslinux_get_keyboard_map(void) { static com32sys_t reg; reg.eax.w[0] = 0x001e; __intcall(0x22, ®, ®); if (!(reg.eflags.l & EFLAGS_CF)) { __syslinux_keyboard_map.version = reg.eax.w[0]; __syslinux_keyboard_map.length = reg.ecx.w[0]; __syslinux_keyboard_map.map = MK_PTR(reg.es, reg.ebx.w[0]); } }
void __constructor __syslinux_get_serial_console_info(void) { static com32sys_t reg; memset(®, 0, sizeof reg); reg.eax.w[0] = 0x000b; __intcall(0x22, ®, ®); __syslinux_serial_console_info.iobase = reg.edx.w[0]; __syslinux_serial_console_info.divisor = reg.ecx.w[0]; __syslinux_serial_console_info.flowctl = reg.ebx.w[0]; }
void execute(const char *cmdline, enum kernel_type type) { com32sys_t ireg; const char *p, * const *pp; char *q = __com32.cs_bounce; const char *kernel, *args; memset(&ireg, 0, sizeof ireg); kernel = q; p = cmdline; while ( *p && !my_isspace(*p) ) { *q++ = *p++; } *q++ = '\0'; args = q; while ( *p && my_isspace(*p) ) p++; strcpy(q, p); if (kernel[0] == '.' && type == KT_NONE) { /* It might be a type specifier */ enum kernel_type type = KT_NONE; for (pp = kernel_types; *pp; pp++, type++) { if (!strcmp(kernel+1, *pp)) { execute(p, type); /* Strip the type specifier and retry */ } } } if (type == KT_LOCALBOOT) { ireg.eax.w[0] = 0x0014; /* Local boot */ ireg.edx.w[0] = strtoul(kernel, NULL, 0); } else { if (type < KT_KERNEL) type = KT_KERNEL; ireg.eax.w[0] = 0x0016; /* Run kernel image */ ireg.esi.w[0] = OFFS(kernel); ireg.ds = SEG(kernel); ireg.ebx.w[0] = OFFS(args); ireg.es = SEG(args); ireg.edx.l = type-KT_KERNEL; /* ireg.ecx.l = 0; */ /* We do ipappend "manually" */ } __intcall(0x22, &ireg, NULL); /* If this returns, something went bad; return to menu */ }
/* Erase a region of the screen */ static void ansicon_erase(const struct term_state *st, int x0, int y0, int x1, int y1) { static com32sys_t ireg; ireg.eax.w[0] = 0x0600; /* Clear window */ ireg.ebx.b[1] = ansicon_attribute(st); ireg.ecx.b[0] = x0; ireg.ecx.b[1] = y0; ireg.edx.b[0] = x1; ireg.edx.b[1] = y1; __intcall(0x10, &ireg, NULL); }
void __constructor __syslinux_get_version(void) { static com32sys_t reg; reg.eax.w[0] = 0x0001; __intcall(0x22, ®, ®); __syslinux_version.version = reg.ecx.w[0]; __syslinux_version.max_api = reg.eax.w[0]; __syslinux_version.filesystem = reg.edx.b[0]; __syslinux_version.version_string = MK_PTR(reg.es, reg.esi.w[0]); __syslinux_version.copyright_string = MK_PTR(reg.es, reg.edi.w[0]); }
static void ansicon_write_char(int x, int y, uint8_t ch, const struct term_state *st) { static com32sys_t ireg; ansicon_set_cursor(x, y, 0); ireg.eax.b[1] = 0x09; ireg.eax.b[0] = ch; ireg.ebx.b[1] = BIOS_PAGE; ireg.ebx.b[0] = ansicon_attribute(st); ireg.ecx.w[0] = 1; __intcall(0x10, &ireg, NULL); }
/* Common setup */ int __ansicon_open(struct file_info *fp) { static com32sys_t ireg; /* Auto-initalized to all zero */ com32sys_t oreg; if (!ansicon_counter) { /* Are we disabled? */ if (syslinux_serial_console_info()->flowctl & 0x8000) { ti.disabled = 1; ti.rows = 25; ti.cols = 80; } else { /* Force text mode */ ireg.eax.w[0] = 0x0005; __intcall(0x22, &ireg, NULL); /* Initial state */ ti.rows = BIOS_ROWS ? BIOS_ROWS+1 : 25; ti.cols = BIOS_COLS; __ansi_init(&ti); /* Get cursor shape and position */ ireg.eax.b[1] = 0x03; ireg.ebx.b[1] = BIOS_PAGE; __intcall(0x10, &ireg, &oreg); cursor_type = oreg.ecx.w[0]; ti.ts->xy.x = oreg.edx.b[0]; ti.ts->xy.y = oreg.edx.b[1]; } } fp->o.rows = ti.rows; fp->o.cols = ti.cols; ansicon_counter++; return 0; }
static ssize_t __stdcon_write(struct file_info *fp, const void *buf, size_t count) { com32sys_t ireg; const char *bufp = buf; size_t n = 0; (void)fp; memset(&ireg, 0, sizeof ireg); ireg.eax.b[1] = 0x02; while (count--) { if (*bufp == '\n') { ireg.edx.b[0] = '\r'; __intcall(0x21, &ireg, NULL); } ireg.edx.b[0] = *bufp++; __intcall(0x21, &ireg, NULL); n++; } return n; }
static void set_window_pos(size_t win_pos) { static com32sys_t ireg; wi.win_pos = win_pos; if (wi.win_num < 0) return; /* This should never happen... */ ireg.eax.w[0] = 0x4F05; ireg.ebx.b[0] = wi.win_num; ireg.edx.w[0] = win_pos >> wi.win_gshift; __intcall(0x10, &ireg, NULL); }
/* * Call int 13h, but with retry on failure. Especially floppies need this. */ static int int13_retry(const com32sys_t *inreg, com32sys_t *outreg) { int retry = 6; /* Number of retries */ com32sys_t tmpregs; if ( !outreg ) outreg = &tmpregs; while ( retry-- ) { __intcall(0x13, inreg, outreg); if ( !(outreg->eflags.l & EFLAGS_CF) ) return 0; /* CF=0, OK */ } return -1; /* Error */ }