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... */ }
void syslinux_run_kernel_image(const char *filename, const char *cmdline, uint32_t ipappend_flags, uint32_t type) { static com32sys_t ireg; char *bbfilename, *bbcmdline, *bbptr; int bytes; bbptr = __com32.cs_bounce; bytes = strlen(filename) + 1; memcpy(bbfilename = bbptr, filename, bytes); bbptr += bytes; bytes = strlen(cmdline) + 1; memcpy(bbcmdline = bbptr, filename, bytes); bbptr += bytes; ireg.eax.w[0] = 0x0016; ireg.ds = SEG(bbfilename); ireg.esi.w[0] = OFFS(bbfilename); ireg.es = SEG(bbcmdline); ireg.ebx.w[0] = OFFS(bbcmdline); ireg.ecx.l = ipappend_flags; ireg.edx.l = type; __intcall(0x22, &ireg, 0); }
void runsyslinuximage(const char*cmd, long ipappend) { unsigned int numfun = 0; char *ptr,*cmdline; getversion(NULL,&numfun); // Function 16h not supported Fall back to runcommand if (numfun < 0x16) runsyslinuxcmd(cmd); // Try the Run Kernel Image function // Split command line into strcpy(__com32.cs_bounce,cmd); ptr = __com32.cs_bounce; // serach for first space or end of string while ( (*ptr) && (*ptr != ' ')) ptr++; if (!*ptr) cmdline = ptr; // no command line else { *ptr++='\0'; // terminate kernal name cmdline = ptr+1; while (*cmdline != ' ') cmdline++; // find first non-space } // Now call the interrupt REG_BX(inreg) = OFFS(cmdline); REG_ES(inreg) = SEG(cmdline); REG_SI(inreg) = OFFS(__com32.cs_bounce); REG_DS(inreg) = SEG(__com32.cs_bounce); REG_EDX(inreg) = 0; __intcall(0x22,&inreg,&outreg); // If successful does not return }
/** write_sectors in write.c has BUG!!! * write_sectors - write several sectors from disk * @drive_info: driveinfo struct describing the disk * @lba: Position to write * @data: Buffer to write * @size: Size of the buffer (number of sectors) * * Return the number of sectors write on success or -1 on failure. * errno_disk contains the error number. **/ static int dwipe_write_sectors(const struct driveinfo *drive_info, const unsigned int lba, const void *data, const int size) { com32sys_t inreg, outreg; struct ebios_dapa *dapa = __com32.cs_bounce; void *buf = (char *)__com32.cs_bounce + size * SECTOR; memcpy(buf, data, size * SECTOR); memset(&inreg, 0, sizeof inreg); if (drive_info->ebios) { dapa->len = sizeof(*dapa); dapa->count = size; dapa->off = OFFS(buf); dapa->seg = SEG(buf); dapa->lba = lba; inreg.esi.w[0] = OFFS(dapa); inreg.ds = SEG(dapa); inreg.edx.b[0] = drive_info->disk; inreg.eax.w[0] = 0x4300; /* Extended write */ } else { unsigned int c, h, s; if (!drive_info->cbios) { // XXX errno /* We failed to get the geometry */ if (lba) return -1; /* Can only write MBR */ s = 1; h = 0; c = 0; } else lba_to_chs(drive_info, lba, &s, &h, &c); // XXX errno if (s > 63 || h > 256 || c > 1023) return -1; inreg.eax.w[0] = 0x0301; /* Write one sector */ inreg.ecx.b[1] = c & 0xff; inreg.ecx.b[0] = s + (c >> 6); inreg.edx.b[1] = h; inreg.edx.b[0] = drive_info->disk; inreg.ebx.w[0] = OFFS(buf); inreg.es = SEG(buf); } /* Perform the write */ if (int13_retry(&inreg, &outreg)) { errno_disk = outreg.eax.b[1]; return -1; /* Give up */ } else return size; }
/* * Boot a specified local disk. AX specifies the BIOS disk number; or * -1 in case we should execute INT 18h ("next device.") */ __export void local_boot(int16_t ax) { com32sys_t ireg, oreg; int i; memset(&ireg, 0, sizeof(ireg)); syslinux_force_text_mode(); writestr(LOCALBOOT_MSG); crlf(); cleanup_hardware(); if (ax == -1) { /* Hope this does the right thing */ __intcall(0x18, &zero_regs, NULL); /* If we returned, oh boy... */ kaboom(); } /* * Load boot sector from the specified BIOS device and jump to * it. */ memset(&ireg, 0, sizeof ireg); ireg.edx.b[0] = ax & 0xff; ireg.eax.w[0] = 0; /* Reset drive */ __intcall(0x13, &ireg, NULL); memset(&ireg, 0, sizeof(ireg)); ireg.eax.w[0] = 0x0201; /* Read one sector */ ireg.ecx.w[0] = 0x0001; /* C/H/S = 0/0/1 (first sector) */ ireg.ebx.w[0] = OFFS(trackbuf); ireg.es = SEG(trackbuf); for (i = 0; i < retry_count; i++) { __intcall(0x13, &ireg, &oreg); if (!(oreg.eflags.l & EFLAGS_CF)) break; } if (i == retry_count) kaboom(); cli(); /* Abandon hope, ye who enter here */ memcpy((void *)0x07C00, trackbuf, 512); ireg.esi.w[0] = OFFS(trackbuf); ireg.edi.w[0] = 0x07C00; ireg.edx.w[0] = ax; call16(local_boot16, &ireg, NULL); }
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 */ }
int __start(void) { int whichfd = atou(__com32.cs_cmdline); static com32sys_t inreg, outreg; /* In bss, so zeroed automatically */ int retry; for (retry = 0; retry < 6; retry++) { printf(">"); inreg.eax.w[0] = 0x0201; /* Read one sector */ inreg.ecx.w[0] = 0x0001; /* Cyl 0 sector 1 */ inreg.edx.b[1] = 0; /* Head 0 */ inreg.edx.b[0] = whichfd; /* Drive number */ inreg.es = SEG(__com32.cs_bounce); /* Read into the bounce buffer */ inreg.ebx.w[0] = OFFS(__com32.cs_bounce); __com32.cs_intcall(0x13, &inreg, &outreg); if ((outreg.eflags.l & 1) == 0) break; } if ((outreg.eflags.l & 1) == 0) { printf("!\n"); inreg.eax.w[0] = 0x000d; inreg.edx.w[0] = 0; inreg.edi.l = (uint32_t) __com32.cs_bounce; inreg.ecx.l = 512; inreg.ebx.l = whichfd & 0xff; inreg.esi.l = 0; /* No partitions */ inreg.ds = 0; /* No partitions */ __com32.cs_intcall(0x22, &inreg, NULL); } /* If we get here, badness happened */ return 255; }
/** * get_drive_parameters_with_extensions - retrieve disk parameters via AH=48h * * INT 13 - IBM/MS INT 13 Extensions - GET DRIVE PARAMETERS * AH = 48h * DL = drive (80h-FFh) * DS:SI -> buffer for drive parameters * Return: CF clear if successful * AH = 00h * DS:SI buffer filled * CF set on error * AH = error code (see #00234) * BUG: several different Compaq BIOSes incorrectly report high-numbered * drives (such as 90h, B0h, D0h, and F0h) as present, giving them the * same geometry as drive 80h; as a workaround, scan through disk * numbers, stopping as soon as the number of valid drives encountered * equals the value in 0040h:0075h **/ static int get_drive_parameters_with_extensions(struct driveinfo *drive_info) { com32sys_t inreg, outreg; struct edd_device_parameters *dp = __com32.cs_bounce; memset(&inreg, 0, sizeof inreg); /* * The caller shall set this value to the maximum Result Buffer * length, in bytes. If the length of this buffer is less than 30 * bytes, this function shall not return the pointer to Drive Parameter * Table (DPT) extension. If the buffer length is 30 or greater on * entry, it shall be set to 30 on exit. If the buffer length is * between 26 and 29, it shall be set to 26 on exit. * If the buffer length is less than 26 on entry an error shall be * returned. */ dp->len = sizeof(struct edd_device_parameters); inreg.esi.w[0] = OFFS(dp); inreg.ds = SEG(dp); inreg.edx.b[0] = drive_info->disk; inreg.eax.b[1] = 0x48; __intcall(0x13, &inreg, &outreg); /* CF set on error */ if (outreg.eflags.l & EFLAGS_CF) return outreg.eax.b[1]; memcpy(&drive_info->edd_params, dp, sizeof drive_info->edd_params); return 0; }
int OS::udp_read(void *buf, const size_t len, uint32_t *from_ip) { int ret = 0; t_PXENV_UDP_READ *pxe_read_param = (t_PXENV_UDP_READ *)lzalloc(sizeof(t_PXENV_UDP_READ) + len); xassert(pxe_read_param); char *buf_reloc = (char *)pxe_read_param + sizeof(*pxe_read_param); pxe_read_param->s_port = htons(UDP_PORT_NO); pxe_read_param->d_port = htons(UDP_PORT_NO); pxe_read_param->buffer.seg = SEG(buf_reloc); pxe_read_param->buffer.offs = OFFS(buf_reloc); pxe_read_param->buffer_size = len; pxeapi_call(PXENV_UDP_READ, (uint8_t *)pxe_read_param); if ((pxe_read_param->status == PXENV_STATUS_SUCCESS) && (pxe_read_param->s_port == htons(UDP_PORT_NO))) { memcpy(buf, buf_reloc, pxe_read_param->buffer_size); *from_ip = pxe_read_param->src_ip; ret = pxe_read_param->buffer_size; } lfree(pxe_read_param); return ret; }
static void gpxecmd(const char **args) { char *q; struct s_PXENV_FILE_EXEC *fx; fx = lmalloc(sizeof *fx); if (!fx) return; q = (char *)(fx + 1); fx->Status = 1; fx->Command.offs = OFFS(q); fx->Command.seg = SEG(q); while (*args) { q = stpcpy(q, *args); *q++ = ' '; args++; } *--q = '\0'; pxe_call(PXENV_FILE_EXEC, fx); /* This should not return... */ }
/* parse_cvt_fnc_t cvt_trimtaip */ static u_long cvt_trimtaip( unsigned char *buffer, int size, struct format *format, clocktime_t *clock_time, void *local ) { long gpsfix; u_char calc_csum = 0; long recv_csum; int i; if (!Strok(buffer, format->fixed_string)) return CVT_NONE; #define OFFS(x) format->field_offsets[(x)].offset #define STOI(x, y) \ Stoi(&buffer[OFFS(x)], y, \ format->field_offsets[(x)].length) if ( STOI(O_DAY, &clock_time->day) || STOI(O_MONTH, &clock_time->month) || STOI(O_YEAR, &clock_time->year) || STOI(O_HOUR, &clock_time->hour) || STOI(O_MIN, &clock_time->minute) || STOI(O_SEC, &clock_time->second) || STOI(O_USEC, &clock_time->usecond)|| STOI(O_GPSFIX, &gpsfix) ) return CVT_FAIL|CVT_BADFMT; clock_time->usecond *= 1000; /* Check that the checksum is right */ for (i=OFFS(O_CHKSUM)-1; i >= 0; i--) calc_csum ^= buffer[i]; recv_csum = (hexval(buffer[OFFS(O_CHKSUM)]) << 4) | hexval(buffer[OFFS(O_CHKSUM)+1]); if (recv_csum < 0) return CVT_FAIL|CVT_BADTIME; if (((u_char) recv_csum) != calc_csum) return CVT_FAIL|CVT_BADTIME; clock_time->utcoffset = 0; /* What should flags be set to ? */ clock_time->flags = PARSEB_UTC; /* if the current GPS fix is 9 (unknown), reject */ if (0 > gpsfix || gpsfix > 9) clock_time->flags |= PARSEB_POWERUP; return CVT_OK; }
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); }
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; }
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); }
void OS::udp_write(const void *buf, const size_t len, uint32_t to_ip) { t_PXENV_UDP_WRITE *pxe_write_param = (t_PXENV_UDP_WRITE *)lzalloc(sizeof(t_PXENV_UDP_WRITE) + len); xassert(pxe_write_param); char *buf_reloc = (char *)pxe_write_param + sizeof(*pxe_write_param); pxe_write_param->ip = to_ip; pxe_write_param->src_port = htons(UDP_PORT_NO); pxe_write_param->dst_port = htons(UDP_PORT_NO); pxe_write_param->buffer.seg = SEG(buf_reloc); pxe_write_param->buffer.offs = OFFS(buf_reloc); pxe_write_param->buffer_size = len; memcpy(buf_reloc, buf, len); pxeapi_call(PXENV_UDP_WRITE, (uint8_t *)pxe_write_param); lfree(pxe_write_param); }
static void dump_e820(void) { com32sys_t ireg, oreg; struct e820_data ed; uint32_t type; 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(__com32.cs_bounce); ireg.es = SEG(__com32.cs_bounce); memset(&ed, 0, sizeof ed); ed.extattr = 1; do { memcpy(__com32.cs_bounce, &ed, sizeof ed); __intcall(0x15, &ireg, &oreg); if (oreg.eflags.l & EFLAGS_CF || oreg.eax.l != 0x534d4150 || oreg.ecx.l < 20) break; memcpy(&ed, __com32.cs_bounce, sizeof ed); if (oreg.ecx.l < 24) ed.extattr = 1; /* 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); 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); }
bool OS::memmap_entry(uint64_t *base, uint64_t *length, uint64_t *type) { state.eax.l = 0xe820; state.edx.l = STR_DW_N("SMAP"); state.ecx.l = sizeof(*ent); state.edi.w[0] = OFFS(ent); state.es = SEG(ent); __intcall(0x15, &state, &state); xassert(state.eax.l == STR_DW_N("SMAP")); // detect if bootloader is called again if (!ent->length) fatal("Bootloader already executed; check boot configuration!"); *base = ent->base; *length = ent->length; *type = ent->type; return state.ebx.l > 0; }
static bool is_gpxe(void) { const struct syslinux_version *sv; com32sys_t reg; struct s_PXENV_FILE_CHECK_API *fca; sv = syslinux_version(); if (sv->filesystem != SYSLINUX_FS_PXELINUX) return false; /* Not PXELINUX */ fca = __com32.cs_bounce; memset(fca, 0, sizeof *fca); fca->Size = sizeof *fca; fca->Magic = 0x91d447b2; memset(®, 0, sizeof reg); reg.eax.w[0] = 0x0009; reg.ebx.w[0] = 0x00e6; /* PXENV_FILE_API_CHECK */ reg.edi.w[0] = OFFS(fca); reg.es = SEG(fca); __intcall(0x22, ®, ®); if (reg.eflags.l & EFLAGS_CF) return false; /* Cannot invoke PXE stack */ if (reg.eax.w[0] || fca->Status) return false; /* PXE failure */ if (fca->Magic != 0xe9c17b20) return false; /* Incorrect magic */ if (fca->Size < sizeof *fca) return false; /* Short return */ if (!(fca->APIMask & (1 << 5))) return false; /* No FILE EXEC */ return true; }
/* * the ASM pxenv function wrapper, return 1 if error, or 0 * */ __export int pxe_call(int opcode, void *data) { static DECLARE_INIT_SEMAPHORE(pxe_sem, 1); extern void pxenv(void); com32sys_t regs; sem_down(&pxe_sem, 0); #if 0 dprintf("pxe_call op %04x data %p\n", opcode, data); #endif memset(®s, 0, sizeof regs); regs.ebx.w[0] = opcode; regs.es = SEG(data); regs.edi.w[0] = OFFS(data); call16(pxenv, ®s, ®s); sem_up(&pxe_sem); return regs.eflags.l & EFLAGS_CF; /* CF SET if fail */ }
/** * read_sectors - read several sectors from disk * @drive_info: driveinfo struct describing the disk * @data: Pre-allocated buffer for output * @lba: Position to read * @sectors: Number of sectors to read * * Return the number of sectors read on success or -1 on failure. * errno_disk contains the error number. **/ int read_sectors(struct driveinfo *drive_info, void *data, const unsigned int lba, const int sectors) { com32sys_t inreg, outreg; struct ebios_dapa *dapa = __com32.cs_bounce; void *buf = (char *)__com32.cs_bounce + sectors * SECTOR; char *bufp = data; if (get_drive_parameters(drive_info) == -1) return -1; memset(&inreg, 0, sizeof inreg); if (drive_info->ebios) { dapa->len = sizeof(*dapa); dapa->count = sectors; dapa->off = OFFS(buf); dapa->seg = SEG(buf); dapa->lba = lba; inreg.esi.w[0] = OFFS(dapa); inreg.ds = SEG(dapa); inreg.edx.b[0] = drive_info->disk; inreg.eax.b[1] = 0x42; /* Extended read */ } else { unsigned int c, h, s; if (!drive_info->cbios) { // XXX errno /* We failed to get the geometry */ if (lba) return -1; /* Can only read MBR */ s = 1; h = 0; c = 0; } else lba_to_chs(drive_info, lba, &s, &h, &c); // XXX errno if (s > 63 || h > 256 || c > 1023) return -1; inreg.eax.w[0] = 0x0201; /* Read one sector */ inreg.ecx.b[1] = c & 0xff; inreg.ecx.b[0] = s + (c >> 6); inreg.edx.b[1] = h; inreg.edx.b[0] = drive_info->disk; inreg.ebx.w[0] = OFFS(buf); inreg.es = SEG(buf); } /* Perform the read */ if (int13_retry(&inreg, &outreg)) { errno_disk = outreg.eax.b[1]; return -1; /* Give up */ } memcpy(bufp, buf, sectors * SECTOR); return sectors; }
static int vesa_getmodes(lua_State *L) { com32sys_t rm; uint16_t mode, *mode_ptr; struct vesa_general_info *gi; struct vesa_mode_info *mi; int nmode = 1; int rv = -1; gi = lmalloc(sizeof *gi); if (!gi) return -1; mi = lmalloc(sizeof *mi); if (!mi) goto out; memset(&rm, 0, sizeof(rm)); memset(gi, 0, sizeof *gi); gi->signature = VBE2_MAGIC; /* Get VBE2 extended data */ rm.eax.w[0] = 0x4F00; /* Get SVGA general information */ rm.edi.w[0] = OFFS(gi); rm.es = SEG(gi); __intcall(0x10, &rm, &rm); if ( rm.eax.w[0] != 0x004F ) goto out; /* Function call failed */ if ( gi->signature != VESA_MAGIC ) { rv = -2; /* No magic */ goto out; } if ( gi->version < 0x0102 ) { rv = -3; /* VESA 1.2+ required */ goto out; } lua_newtable(L); /* list of modes */ /* Copy general info */ memcpy(&__vesa_info.gi, gi, sizeof *gi); /* Search for a 640x480 mode with a suitable color and memory model... */ mode_ptr = GET_PTR(gi->video_mode_ptr); while ((mode = *mode_ptr++) != 0xFFFF) { mode &= 0x1FF; /* The rest are attributes of sorts */ printf("Found mode: 0x%04x (%dx%dx%d)\n", mode, mi->h_res, mi->v_res, mi->bpp); memset(&rm, 0, sizeof(rm)); memset(mi, 0, sizeof *mi); rm.eax.w[0] = 0x4F01; /* Get SVGA mode information */ rm.ecx.w[0] = mode; rm.edi.w[0] = OFFS(mi); rm.es = SEG(mi); __intcall(0x10, &rm, &rm); /* Must be a supported mode */ if ( rm.eax.w[0] != 0x004f ) continue; lua_pushnumber(L, nmode++); lua_newtable(L); /* mode info */ lua_pushstring(L, "mode"); lua_pushnumber(L, mode); lua_settable(L,-3); lua_pushstring(L, "hres"); lua_pushnumber(L, mi->h_res); lua_settable(L,-3); lua_pushstring(L, "vres"); lua_pushnumber(L, mi->v_res); lua_settable(L,-3); lua_pushstring(L, "bpp"); lua_pushnumber(L, mi->bpp); lua_settable(L,-3); lua_settable(L, -3); /* add to mode list */ } rv = 1; out: lfree(mi); lfree(gi); return rv; }
static void print_modes(void) { static com32sys_t rm; struct vesa_general_info *gi; struct vesa_mode_info *mi; uint16_t mode, *mode_ptr; int lines; struct vesa_info *vesa; vesa = lmalloc(sizeof(*vesa)); if (!vesa) { printf("vesainfo.c32: fail in lmalloc\n"); return; } gi = &vesa->gi; mi = &vesa->mi; memset(&rm, 0, sizeof rm); gi->signature = VBE2_MAGIC; /* Get VBE2 extended data */ rm.eax.w[0] = 0x4F00; /* Get SVGA general information */ rm.edi.w[0] = OFFS(gi); rm.es = SEG(gi); __intcall(0x10, &rm, &rm); if (rm.eax.w[0] != 0x004F) { printf("No VESA BIOS detected\n"); goto exit; } else if (gi->signature != VESA_MAGIC) { printf("VESA information structure has bad magic, trying anyway...\n"); } printf("VBE version %d.%d\n" "Mode attrib h_res v_res bpp layout rpos gpos bpos\n", (gi->version >> 8) & 0xff, gi->version & 0xff); lines = 1; mode_ptr = GET_PTR(gi->video_mode_ptr); while ((mode = *mode_ptr++) != 0xFFFF) { if (++lines >= 23) { wait_key(); lines = 0; } memset(&rm, 0, sizeof rm); rm.eax.w[0] = 0x4F01; /* Get SVGA mode information */ rm.ecx.w[0] = mode; rm.edi.w[0] = OFFS(mi); rm.es = SEG(mi); __intcall(0x10, &rm, &rm); /* Must be a supported mode */ if (rm.eax.w[0] != 0x004f) continue; printf("0x%04x 0x%04x %5u %5u %3u %6u %4u %4u %4u\n", mode, mi->mode_attr, mi->h_res, mi->v_res, mi->bpp, mi->memory_layout, mi->rpos, mi->gpos, mi->bpos); } exit: lfree(vesa); return; }
/* ********** extern stuff **********/ extern env_t* env_ptr; /* common/env_<nand/eeprom>.c */ extern int _do_setenv( int flag, int argc, char *argv[] ); /* common/cmd_nvedit.c */ extern int _do_orig_setenv (int flag, int argc, char *argv[]); /* ********** local functions **********/ static const env_param_t* EnvVarInNVRAM( const char* szArg ); static int EnvVarStoreToNVRAM( const env_param_t* pParam, const char* szVal ); /* ********** local variables **********/ static const env_param_t l_axParam[] = { { "ethaddr", ENV_MAC, OFFS( xID.axMAC[ 0 ] ), 1 }, { "wlanaddr", ENV_MAC, OFFS( xID.axMAC[ 1 ] ), 1 }, { "eth1addr", ENV_MAC, OFFS( eth1addr ), 1 }, { "btaddr", ENV_MAC, OFFS( btaddr1 ), 1 }, { "ipaddr", ENV_IP, OFFS( xIP.axDevice[ 0 ].uiIP ) }, { "ipaddr_wlan", ENV_IP, OFFS( xIP.axDevice[ 1 ].uiIP ) }, { "ipaddr1", ENV_IP, OFFS( eth1dev.uiIP ) }, { "netmask", ENV_IP, OFFS( xIP.axDevice[ 0 ].uiNetMask ) }, { "netmask_wlan", ENV_IP, OFFS( xIP.axDevice[ 1 ].uiNetMask ) }, { "netmask1", ENV_IP, OFFS( eth1dev.uiNetMask ) }, { "serverip", ENV_IP, OFFS( xIP.uiIPServer ) }, { "gatewayip", ENV_IP, OFFS( xIP.uiIPGateway) }, { "dnsip", ENV_IP, OFFS( xIP.auiIPDNS[ 0 ] ) }, { "dnsip2", ENV_IP, OFFS( xIP.auiIPDNS[ 1 ] ) }, { "dhcp", ENV_BOOL_ON, OFFS( xIP.axDevice[ 0 ].flags.bDHCP ) }, { "dhcp_wlan", ENV_BOOL_ON, OFFS( xIP.axDevice[ 1 ].flags.bDHCP ) },
BACKGROUNDPEN, TEXTPEN, FILLPEN, HIGHLIGHTTEXTPEN, SHINEPEN, TEXTPEN, SHINEPEN, SHADOWPEN, BACKGROUNDPEN, TEXTPEN, -4, BACKGROUNDPEN }; /** Which part of editor to modify according to color changes **/ UBYTE Modif[] = { EDIT_AREA, EDIT_AREA, EDIT_AREA, EDIT_AREA, 0, 0, EDIT_GUI, EDIT_GUI, EDIT_GUI, EDIT_GUI, EDIT_GUI, EDIT_GUI }; /** Little wrapper **/ #define OFFS(x) (UBYTE)(offsetof(PREFS,x)) /** Offset of structure PREFS **/ UBYTE offsets[] = { OFFS(use_pub), OFFS(wordssep), OFFS(attrtxt), OFFS(attrtxt.ta_YSize), OFFS(attrscr), OFFS(attrscr.ta_YSize), OFFS(left), OFFS(scrw), OFFS(scrd), OFFS(modeid), OFFS(vmd), OFFS(pen) }; /** And correspond size (0=null-terminated string) **/ UBYTE sizefields[] = { 12*sizeof(char), 0, 0, sizeof(prefs.attrtxt)-sizeof(STRPTR), 0, sizeof(prefs.attrscr)-sizeof(STRPTR), 4*sizeof(prefs.left), sizeof(prefs.scrw), sizeof(prefs.scrd), sizeof(prefs.modeid), sizeof(prefs.vmd), sizeof(prefs.pen) }; UBYTE FontName[60]; /*** Convert a TextFont struct into a TextAttr ***/ void text_to_attr(struct TextFont *src, struct TextAttr *dest) {
static int mboot_scan_memory(struct AddrRangeDesc **ardp, uint32_t * dosmem) { com32sys_t ireg, oreg; struct e820_entry *e820buf = __com32.cs_bounce; struct AddrRangeDesc *ard; size_t ard_count, ard_space; /* Use INT 12h to get DOS memory */ __intcall(0x12, &__com32_zero_regs, &oreg); *dosmem = oreg.eax.w[0] << 10; if (*dosmem < 32 * 1024 || *dosmem > 640 * 1024) { /* INT 12h reports nonsense... now what? */ uint16_t ebda_seg = *(uint16_t *) 0x40e; if (ebda_seg >= 0x8000 && ebda_seg < 0xa000) *dosmem = ebda_seg << 4; else *dosmem = 640 * 1024; /* Hope for the best... */ } /* Allocate initial space */ *ardp = ard = malloc(RANGE_ALLOC_BLOCK * sizeof *ard); if (!ard) return 0; ard_count = 0; ard_space = RANGE_ALLOC_BLOCK; /* First try INT 15h AX=E820h */ memset(&ireg, 0, sizeof ireg); ireg.eax.l = 0xe820; ireg.edx.l = 0x534d4150; /* ireg.ebx.l = 0; */ ireg.ecx.l = sizeof(*e820buf); ireg.es = SEG(e820buf); ireg.edi.w[0] = OFFS(e820buf); memset(e820buf, 0, sizeof *e820buf); do { __intcall(0x15, &ireg, &oreg); if ((oreg.eflags.l & EFLAGS_CF) || (oreg.eax.l != 0x534d4150) || (oreg.ecx.l < 20)) break; if (ard_count >= ard_space) { ard_space += RANGE_ALLOC_BLOCK; *ardp = ard = realloc(ard, ard_space * sizeof *ard); if (!ard) return ard_count; } ard[ard_count].size = 20; ard[ard_count].BaseAddr = e820buf->start; ard[ard_count].Length = e820buf->len; ard[ard_count].Type = e820buf->type; ard_count++; ireg.ebx.l = oreg.ebx.l; } while (oreg.ebx.l); if (ard_count) return ard_count; ard[0].size = 20; ard[0].BaseAddr = 0; ard[0].Length = *dosmem << 10; ard[0].Type = 1; /* Next try INT 15h AX=E801h */ ireg.eax.w[0] = 0xe801; __intcall(0x15, &ireg, &oreg); if (!(oreg.eflags.l & EFLAGS_CF) && oreg.ecx.w[0]) { ard[1].size = 20; ard[1].BaseAddr = 1 << 20; ard[1].Length = oreg.ecx.w[0] << 10; ard[1].Type = 1; if (oreg.edx.w[0]) { ard[2].size = 20; ard[2].BaseAddr = 16 << 20; ard[2].Length = oreg.edx.w[0] << 16; ard[2].Type = 1; return 3; } else { return 2; } } /* Finally try INT 15h AH=88h */ ireg.eax.w[0] = 0x8800; if (!(oreg.eflags.l & EFLAGS_CF) && oreg.eax.w[0]) { ard[1].size = 20; ard[1].BaseAddr = 1 << 20; ard[1].Length = oreg.ecx.w[0] << 10; ard[1].Type = 1; return 2; } return 1; /* ... problematic ... */ }
* Lua timer class */ #define OFFS(m) MRP_OFFSET(timer_lua_t, m) #define RDONLY MRP_LUA_CLASS_READONLY #define NOTIFY MRP_LUA_CLASS_NOTIFY #define NOFLAGS MRP_LUA_CLASS_NOFLAGS MRP_LUA_METHOD_LIST_TABLE(timer_lua_methods, MRP_LUA_METHOD_CONSTRUCTOR(timer_lua_create)); MRP_LUA_METHOD_LIST_TABLE(timer_lua_overrides, MRP_LUA_OVERRIDE_CALL (timer_lua_create)); MRP_LUA_MEMBER_LIST_TABLE(timer_lua_members, MRP_LUA_CLASS_INTEGER("interval", OFFS(msecs) , NULL, NULL, NOTIFY) MRP_LUA_CLASS_LFUNC ("callback", OFFS(callback), NULL, NULL, NOTIFY) MRP_LUA_CLASS_ANY ("data" , OFFS(data) , NULL, NULL, NOTIFY) MRP_LUA_CLASS_BOOLEAN("oneshot" , OFFS(oneshot) , NULL, NULL, NOTIFY)); typedef enum { TIMER_MEMBER_INTERVAL, TIMER_MEMBER_CALLBACK, TIMER_MEMBER_DATA, TIMER_MEMBER_ONESHOT } timer_member_t; MRP_LUA_DEFINE_CLASS(timer, lua, timer_lua_t, timer_lua_destroy, timer_lua_methods, timer_lua_overrides, timer_lua_members, NULL, timer_lua_changed,
static int chs_rdwr_sectors(struct disk *disk, void *buf, sector_t lba, size_t count, bool is_write) { char *ptr = buf; char *tptr; size_t chunk, freeseg; int sector_shift = disk->sector_shift; uint32_t xlba = lba + disk->part_start; /* Truncated LBA (CHS is << 2 TB) */ uint32_t t; uint32_t c, h, s; com32sys_t ireg, oreg; size_t done = 0; size_t bytes; int retry; uint32_t maxtransfer = disk->maxtransfer; if (lba + disk->part_start >= chs_max(disk)) return 0; /* Impossible CHS request */ memset(&ireg, 0, sizeof ireg); ireg.eax.b[1] = 0x02 + is_write; ireg.edx.b[0] = disk->disk_number; while (count) { chunk = count; if (chunk > maxtransfer) chunk = maxtransfer; freeseg = (0x10000 - ((size_t)ptr & 0xffff)) >> sector_shift; if ((size_t)buf <= 0xf0000 && freeseg) { /* Can do a direct load */ tptr = ptr; } else { /* Either accessing high memory or we're crossing a 64K line */ tptr = core_xfer_buf; freeseg = (0x10000 - ((size_t)tptr & 0xffff)) >> sector_shift; } if (chunk > freeseg) chunk = freeseg; s = xlba % disk->s; t = xlba / disk->s; h = t % disk->h; c = t / disk->h; if (chunk > (disk->s - s)) chunk = disk->s - s; bytes = chunk << sector_shift; if (tptr != ptr && is_write) memcpy(tptr, ptr, bytes); ireg.eax.b[0] = chunk; ireg.ecx.b[1] = c; ireg.ecx.b[0] = ((c & 0x300) >> 2) | (s+1); ireg.edx.b[1] = h; ireg.ebx.w[0] = OFFS(tptr); ireg.es = SEG(tptr); retry = RETRY_COUNT; for (;;) { if (c < 1024) { dprintf("CHS[%02x]: %u @ %llu (%u/%u/%u) %04x:%04x %s %p\n", ireg.edx.b[0], chunk, xlba, c, h, s+1, ireg.es, ireg.ebx.w[0], (ireg.eax.b[1] & 1) ? "<-" : "->", ptr); __intcall(0x13, &ireg, &oreg); if (!(oreg.eflags.l & EFLAGS_CF)) break; dprintf("CHS: error AX = %04x\n", oreg.eax.w[0]); if (retry--) continue; /* * For any starting value, this will always end with * ..., 1, 0 */ chunk >>= 1; if (chunk) { maxtransfer = chunk; retry = RETRY_COUNT; ireg.eax.b[0] = chunk; continue; } } printf("CHS: Error %04x %s sector %llu (%u/%u/%u)\n", oreg.eax.w[0], is_write ? "writing" : "reading", lba, c, h, s+1); return done; /* Failure */ } bytes = chunk << sector_shift; if (tptr != ptr && !is_write) memcpy(ptr, tptr, bytes); /* If we dropped maxtransfer, it eventually worked, so remember it */ disk->maxtransfer = maxtransfer; ptr += bytes; xlba += chunk; count -= chunk; done += chunk; }
{ "double-density-3-1/2", 12, 80, 2, 9 }, { "720k", 12, 80, 2, 9 }, { "dd514", 12, 40, 2, 9 }, { "double-density-5-1/4", 12, 40, 2, 9 }, { "360k", 12, 40, 2, 9 }, { "320k", 12, 40, 2, 8 }, { "180k", 12, 40, 1, 9 }, { "160k", 12, 40, 1, 8 } }; #define OFFS(x) ((caddr_t)&((struct device *)0)->x) static switches_t dswitches[]= { { "FILE", OFFS(name), T_STRING }, { "OFFSET", OFFS(offset), T_UINT }, { "PARTITION", OFFS(partition), T_UINT }, { "FAT", OFFS(fat_bits), T_INT }, { "FAT_BITS", OFFS(fat_bits), T_UINT }, { "MODE", OFFS(mode), T_UINT }, { "TRACKS", OFFS(tracks), T_UINT }, { "CYLINDERS", OFFS(tracks), T_UINT }, { "HEADS", OFFS(heads), T_UINT }, { "SECTORS", OFFS(sectors), T_UINT }, { "HIDDEN", OFFS(hidden), T_UINT }, { "PRECMD", OFFS(precmd), T_STRING }, { "BLOCKSIZE", OFFS(blocksize), T_UINT }, { "CODEPAGE", OFFS(codepage), T_UINT } };
/* parse_cvt_fnc_t cvt_hopf6021 */ static u_long cvt_hopf6021( unsigned char *buffer, int size, struct format *format, clocktime_t *clock_time, void *local ) { unsigned char status,weekday; if (!Strok(buffer, format->fixed_string)) { return CVT_NONE; } if ( STOI(O_DAY, &clock_time->day) || STOI(O_MONTH, &clock_time->month) || STOI(O_YEAR, &clock_time->year) || STOI(O_HOUR, &clock_time->hour) || STOI(O_MIN, &clock_time->minute) || STOI(O_SEC, &clock_time->second) ) { return CVT_FAIL|CVT_BADFMT; } clock_time->usecond = 0; clock_time->utcoffset = 0; status = (u_char) hexval(buffer[OFFS(O_FLAGS)]); weekday= (u_char) hexval(buffer[OFFS(O_WDAY)]); if ((status == 0xFF) || (weekday == 0xFF)) { return CVT_FAIL|CVT_BADFMT; } clock_time->flags = 0; if (weekday & HOPF_UTC) { clock_time->flags |= PARSEB_UTC; } else { if (status & HOPF_DST) { clock_time->flags |= PARSEB_DST; clock_time->utcoffset = -2*60*60; /* MET DST */ } else { clock_time->utcoffset = -1*60*60; /* MET */ } } clock_time->flags |= (status & HOPF_DSTWARN) ? PARSEB_ANNOUNCE : 0; switch (status & HOPF_MODE) { case HOPF_INVALID: /* Time/Date invalid */ clock_time->flags |= PARSEB_POWERUP; break; case HOPF_INTERNAL: /* internal clock */ clock_time->flags |= PARSEB_NOSYNC; break; case HOPF_RADIO: /* Radio clock */ case HOPF_RADIOHP: /* Radio clock high precision */ break; default: return CVT_FAIL|CVT_BADFMT; } return CVT_OK; }
void set_graphics_mode(const struct multiboot_header *mbh, struct multiboot_info *mbi) { com32sys_t rm; uint16_t mode, bestmode, *mode_ptr; struct vesa_general_info *gi; struct vesa_mode_info *mi; int pxf, bestpxf; int wantx, wanty; int err, besterr; bool better; addr_t viaddr; /* Only do this if requested by the OS image */ if (!(mbh->flags & MULTIBOOT_VIDEO_MODE) || mbh->mode_type != 0) return; gi = lmalloc(sizeof *gi); if (!gi) return; mi = lmalloc(sizeof *mi); if (!mi) goto out; memset(&rm, 0, sizeof rm); memset(gi, 0, sizeof *gi); gi->signature = VBE2_MAGIC; /* Get VBE2 extended data */ rm.eax.w[0] = 0x4F00; /* Get SVGA general information */ rm.edi.w[0] = OFFS(gi); rm.es = SEG(gi); __intcall(0x10, &rm, &rm); if (rm.eax.w[0] != 0x004F) goto out; /* Function call failed */ if (gi->signature != VESA_MAGIC) goto out; /* No magic */ if (gi->version < 0x0102) goto out; /* VESA 1.2+ required */ memcpy(&vesa_info.gi, gi, sizeof *gi); /* Search for a suitable mode with a suitable color and memory model... */ mode_ptr = GET_PTR(gi->video_mode_ptr); bestmode = 0; bestpxf = 0; wantx = mbh->width ? mbh->width : 0xffff; wanty = mbh->height ? mbh->height : 0xffff; besterr = wantx + wanty; while ((mode = *mode_ptr++) != 0xFFFF) { mode &= 0x1FF; /* The rest are attributes of sorts */ memset(&rm, 0, sizeof rm); memset(mi, 0, sizeof *mi); rm.eax.w[0] = 0x4F01; /* Get SVGA mode information */ rm.ecx.w[0] = mode; rm.edi.w[0] = OFFS(mi); rm.es = SEG(mi); __intcall(0x10, &rm, &rm); /* Must be a supported mode */ if (rm.eax.w[0] != 0x004f) continue; /* Must be an LFB color graphics mode supported by the hardware. The bits tested are: 7 - linear frame buffer 4 - graphics mode 3 - color mode 1 - mode information available (mandatory in VBE 1.2+) 0 - mode supported by hardware */ if ((mi->mode_attr & 0x009b) != 0x009b) continue; /* We don't support multibank (interlaced memory) modes */ /* * Note: The Bochs VESA BIOS (vbe.c 1.58 2006/08/19) violates the * specification which states that banks == 1 for unbanked modes; * fortunately it does report bank_size == 0 for those. */ if (mi->banks > 1 && mi->bank_size) continue; /* Must either be a packed-pixel mode or a direct color mode (depending on VESA version ); must be a supported pixel format */ if (mi->bpp == 32 && (mi->memory_layout == 4 || (mi->memory_layout == 6 && mi->rpos == 16 && mi->gpos == 8 && mi->bpos == 0))) pxf = 32; else if (mi->bpp == 24 && (mi->memory_layout == 4 || (mi->memory_layout == 6 && mi->rpos == 16 && mi->gpos == 8 && mi->bpos == 0))) pxf = 24; else if (mi->bpp == 16 && (mi->memory_layout == 4 || (mi->memory_layout == 6 && mi->rpos == 11 && mi->gpos == 5 && mi->bpos == 0))) pxf = 16; else if (mi->bpp == 15 && (mi->memory_layout == 4 || (mi->memory_layout == 6 && mi->rpos == 10 && mi->gpos == 5 && mi->bpos == 0))) pxf = 15; else continue; better = false; err = abs(mi->h_res - wantx) + abs(mi->v_res - wanty); #define IS_GOOD(mi, bestx, besty) \ ((mi)->h_res >= (bestx) && (mi)->v_res >= (besty)) if (!bestpxf) better = true; else if (!IS_GOOD(&vesa_info.mi, wantx, wanty) && IS_GOOD(mi, wantx, wanty)) /* This matches criteria, which the previous one didn't */ better = true; else if (IS_GOOD(&vesa_info.mi, wantx, wanty) && !IS_GOOD(mi, wantx, wanty)) /* This doesn't match criteria, and the previous one did */ better = false; else if (err < besterr) better = true; else if (err == besterr && (pxf == (int)mbh->depth || pxf > bestpxf)) better = true; if (better) { bestmode = mode; bestpxf = pxf; memcpy(&vesa_info.mi, mi, sizeof *mi); } } if (!bestpxf) goto out; /* No mode found */ mi = &vesa_info.mi; mode = bestmode; /* Now set video mode */ memset(&rm, 0, sizeof rm); rm.eax.w[0] = 0x4F02; /* Set SVGA video mode */ mode |= 0x4000; /* Request linear framebuffer */ rm.ebx.w[0] = mode; __intcall(0x10, &rm, &rm); if (rm.eax.w[0] != 0x004F) goto out; /* Failed to set mode */ mbi->flags |= MB_INFO_VIDEO_INFO; mbi->vbe_mode = mode; viaddr = map_data(&vesa_info, sizeof vesa_info, 4, 0); mbi->vbe_control_info = viaddr + offsetof(struct vesa_info, gi); mbi->vbe_mode_info = viaddr + offsetof(struct vesa_info, mi); /* Get the VBE 2.x PM entry point if supported */ rm.eax.w[0] = 0x4F0A; rm.ebx.w[0] = 0; __intcall(0x10, &rm, &rm); if (rm.eax.w[0] == 0x004F) { mbi->vbe_interface_seg = rm.es; mbi->vbe_interface_off = rm.edi.w[0]; mbi->vbe_interface_len = rm.ecx.w[0]; } /* In theory this should be: * * UsingVga = (mi->mode_attr & 4) ? 0x0007 : 0x000f; * * However, that would assume all systems that claim to handle text * output in VESA modes actually do that... */ graphics_using_vga(0x0F, vesa_info.mi.h_res, vesa_info.mi.v_res); out: lfree(mi); lfree(gi); }