int hdd_io(int hdd_n, void *buff, u16 sectors, u64 start, int read) { u8 sbuf[32]; rm_ctx ctx; u32 head, cyl; u8 dos_n = hdd2dos(hdd_n); hdd_inf *hdd = &iodb.p_hdd[hdd_n]; lba_p *lba = pv(0x580); /* this needed for avoid stupid actions by buggy BIOSes */ int succs = 0; /* setup initial context */ set_ctx(0, &ctx); if (hdd->flags & HDD_LBA) { /* save old buffer */ mincpy(sbuf, lba, sizeof(sbuf)); /* setup LBA block */ lba->size = sizeof(lba_p); lba->unk = 0; lba->dst_sel = rm_seg(buff); lba->dst_off = rm_off(buff); lba->numb = sectors; lba->sector = start; ctx.ah = read ? 0x42:0x43; ctx.dl = dos_n; ctx.si = 0x180; ctx.ds = 0x40; /* if DS can be 0x40, we can avoid AWARD BIOS bug of int13/AX=4B01 */ /* set additional registers to serve buggy BIOSes. */ ctx.es = ctx.ds; ctx.di = ctx.si; ctx.bx = ctx.si; ctx.cx = ctx.ds; /* do not check AH because some buggy USB BIOSes fail to clear AH on success */ succs = bios_call(0x13, &ctx); /* restore saved buffer */ mincpy(lba, sbuf, sizeof(sbuf)); } else { head = d32(start) / hdd->max_sect; cyl = head / hdd->max_head; ctx.ah = read ? 0x02:0x03; ctx.al = d8(sectors); ctx.ch = d8(cyl); ctx.cl = d8(((cyl & 0x0300) >> 2) | (d32(start) % hdd->max_sect + 1)); ctx.dh = head % hdd->max_head; ctx.dl = dos_n; ctx.es = rm_seg(buff); ctx.bx = rm_off(buff); /* do not check AH because some buggy USB BIOSes fail to clear AH on success */ succs = bios_call(0x13, &ctx); } return succs; }
static int get_memory_map_entry(uint32_t * token, struct memory_map_entry * entry) { struct memory_map_entry buf; struct registers regs; regs.eax = 0xE820; regs.ebx = *token; regs.ecx = sizeof(struct memory_map_entry); regs.edx = 0x534D4150; regs.es = segment_of(&buf); regs.di = offset_of(&buf); bios_call(®s, 0x15); if ((regs.flags & 1) != 0) /* CF set - error */ return 1; if (regs.eax != 0x534D4150) return 2; *token = regs.ebx; entry->address = buf.address; entry->size = buf.size; entry->type = buf.type; entry->ext = buf.ext; return 0; }
/** * Get the PXE entry point address. * * @return Whether the entry point could be found. */ static bool get_entry_point(void) { bios_regs_t regs; pxenv_t *pxenv; pxe_t *pxe; /* Use the PXE installation check function. */ bios_regs_init(®s); regs.eax = INT1A_PXE_INSTALL_CHECK; bios_call(0x1a, ®s); if (regs.eax != INT1A_PXE_INSTALL_CHECK_RET || regs.eflags & X86_FLAGS_CF) { dprintf("pxe: loaded via PXE but PXE not available\n"); return false; } /* Get the PXENV+ structure. */ pxenv = (pxenv_t *)segoff_to_linear((regs.es << 16) | regs.bx); if (memcmp(pxenv->signature, PXENV_SIGNATURE, sizeof(pxenv->signature)) != 0) { boot_error("PXENV+ structure has incorrect signature"); } else if (!checksum_range(pxenv, pxenv->length)) { boot_error("PXENV+ structure is corrupt"); } /* Get the !PXE structure. */ pxe = (pxe_t *)segoff_to_linear(pxenv->pxe_ptr); if (memcmp(pxe->signature, PXE_SIGNATURE, sizeof(pxe->signature)) != 0) { boot_error("!PXE structure has incorrect signature"); } else if (!checksum_range(pxe, pxe->length)) { boot_error("!PXE structure is corrupt"); } pxe_entry_point = pxe->entry_point_16; return true; }
static void dc_password_error(prt_inf *active) { if (conf.error_type & ET_MESSAGE) { puts(conf.err_msg); } if (conf.error_type & ET_REBOOT) { bios_reboot(); } if (conf.error_type & ET_BOOT_ACTIVE) { if (active == NULL) { puts("active partition not found\n"); } else { boot_from_partition(active, 0); } } if (conf.error_type & ET_EXIT_TO_BIOS) { bios_call(0x18, NULL); } if (conf.error_type & ET_MBR_BOOT) { autocpy(pv(0x7C00), conf.save_mbr, SECTOR_SIZE); bios_jump_boot(boot_dsk, 0); } }
uint32_t get_low_memory_limit() { struct registers regs; bios_call(®s, 0x12); return regs.ax * 1024; }