From 44b5d0961807a99a309f383bbbd3dafd6ec51ecb Mon Sep 17 00:00:00 2001 From: hpa Date: Fri, 3 Dec 2004 23:16:31 +0000 Subject: [PATCH] The chain loader has been moved to the main com32 directory. --- sample/Makefile | 4 +- sample/chain.c | 368 -------------------------------------------------------- 2 files changed, 2 insertions(+), 370 deletions(-) delete mode 100644 sample/chain.c diff --git a/sample/Makefile b/sample/Makefile index 0e7281c..ec341cb 100644 --- a/sample/Makefile +++ b/sample/Makefile @@ -30,14 +30,14 @@ SFLAGS = -march=i386 LDFLAGS = -s OBJCOPY = objcopy PPMTOLSS16 = ../ppmtolss16 -LIB = libcom32.a +LIB = liboldcom32.a LIBOBJS = conio.o atou.o skipatou.o printf.o c32exit.o .SUFFIXES: .lss .c .o .elf .c32 all: syslogo.lss comecho.com hello.c32 hello2.c32 filetest.c32 c32echo.c32 \ - fd.c32 chain.c32 $(LIB) + fd.c32 $(LIB) .PRECIOUS: %.o %.o: %.S diff --git a/sample/chain.c b/sample/chain.c deleted file mode 100644 index 115b137..0000000 --- a/sample/chain.c +++ /dev/null @@ -1,368 +0,0 @@ -#ident "$Id$" -/* ----------------------------------------------------------------------- * - * - * Copyright 2003 H. Peter Anvin - All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, Inc., 53 Temple Place Ste 330, - * Bostom MA 02111-1307, USA; either version 2 of the License, or - * (at your option) any later version; incorporated herein by reference. - * - * ----------------------------------------------------------------------- */ - -/* - * chain.c - * - * Chainload a hard disk (currently rather braindead.) - * - * Usage: chain hd [] - * chain fd - * - * ... e.g. "chain hd0 1" will boot the first partition on the first hard disk. - * - * Only partitions 1-4 supported at this time; 0 = boot MBR (default.) - */ - -#include -#define NULL ((void *)0) - -int printf(const char *, ...); -int puts(const char *); -unsigned int skip_atou(char * const *); - -#define memset(x,y,z) __builtin_memset(x,y,z) -#define memcpy(x,y,z) __builtin_memcpy(x,y,z) - -#define SECTOR 512 /* bytes/sector */ - -static inline void error(const char *msg) -{ - puts(msg); -} - -static inline int isspace(char x) -{ - return (x == ' ') || (x >= '\b' && x <= '\r'); -} - -/* - * Call int 13h, but with retry on failure. Especially floppies need this. - */ -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 ) { - __com32.cs_intcall(0x13, inreg, outreg); - if ( (outreg->eflags.l & 1) == 0 ) - return 0; /* CF=0, OK */ - } - - return -1; /* Error */ -} - -/* - * Query disk parameters and EBIOS availability for a particular disk. - */ -struct diskinfo { - int disk; - int head; - int sect; - int ebios; -} disk_info; - -int get_disk_params(int disk) -{ - com32sys_t getparm, parm, getebios, ebios; - - memset(&getparm, 0, sizeof getparm); - memset(&getebios, 0, sizeof getebios); - memset(&disk_info, 0, sizeof disk_info); - - disk_info.disk = disk; - - if ( disk & 0x80 ) { - /* Get disk parameters -- hard drives only */ - - getparm.eax.b[1] = 0x08; - getparm.edx.b[0] = disk; - if ( int13_retry(&getparm, &parm) ) - return -1; - - disk_info.head = parm.edx.b[1]+1; - disk_info.sect = parm.ecx.b[0] & 0x3f; - - /* Get EBIOS support */ - - getebios.eax.w[0] = 0x4100; - getebios.edx.b[0] = disk; - getebios.ebx.w[0] = 0x55aa; - getebios.eflags.b[0] = 0x3; /* CF set */ - if ( !int13_retry(&getebios, &ebios) ) { - if ( ebios.ebx.w[0] == 0xaa55 && - (ebios.ecx.b[0] & 1) ) - disk_info.ebios = 1; - } - } - - return 0; -} - -/* - * Get a disk block; buf is REQUIRED TO BE IN LOW MEMORY. - */ -struct ebios_dapa { - uint16_t len; - uint16_t count; - uint16_t off; - uint16_t seg; - uint64_t lba; -} *dapa; - -int read_sector(void *buf, unsigned int lba) -{ - com32sys_t inreg; - - memset(&inreg, 0, sizeof inreg); - - if ( disk_info.ebios ) { - dapa->len = sizeof(*dapa); - dapa->count = 1; /* 1 sector */ - 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] = disk_info.disk; - inreg.eax.b[1] = 0x42; /* Extended read */ - } else { - unsigned int c, h, s, t; - - s = (lba % disk_info.sect) + 1; - t = lba / disk_info.sect; /* Track = head*cyl */ - h = t % disk_info.head; - c = t / disk_info.head; - - 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] = disk_info.disk; - inreg.ebx.w[0] = OFFS(buf); - inreg.es = SEG(buf); - } - - return int13_retry(&inreg, NULL); -} - -/* A DOS partition table entry */ -struct part_entry { - uint8_t active_flag; /* 0x80 if "active" */ - uint8_t start_head; - uint8_t start_sect; - uint8_t start_cyl; - uint8_t ostype; - uint8_t end_head; - uint8_t end_sect; - uint8_t end_cyl; - uint32_t start_lba; - uint32_t length; -} __attribute__((packed)); - - -/* Search for a logical partition. Logical partitions are actually implemented - as recursive partition tables; theoretically they're supposed to form a linked - list, but other structures have been seen. - - To make things extra confusing: data partition offsets are relative to where - the data partition record is stored, whereas extended partition offsets - are relative to the beginning of the extended partition all the way back - at the MBR... but still not absolute! */ - -int nextpart; /* Number of the next logical partition */ - -struct part_entry *find_logical_partition(int whichpart, char *table, struct part_entry *self, struct part_entry *root) -{ - struct part_entry *ptab = (struct part_entry *)(table + 0x1be); - struct part_entry *found; - int i; - - if ( *(uint16_t *)(ptab + 0x1fe) != 0xaa55 ) - return NULL; /* Signature missing */ - - /* We are assumed to already having enumerated all the data partitions - in this table if this is the MBR. For MBR, self == NULL. */ - - if ( self ) { - /* Scan the data partitions. */ - - for ( i = 0 ; i < 4 ; i++ ) { - if ( ptab[i].ostype == 0x00 || ptab[i].ostype == 0x05 || - ptab[i].ostype == 0x0f || ptab[i].ostype == 0x85 ) - continue; /* Skip empty or extended partitions */ - - if ( !ptab[i].length ) - continue; - - /* Adjust the offset to account for the extended partition itself */ - ptab[i].start_lba += self->start_lba; - - /* Sanity check entry: must not extend outside the extended partition. - This is necessary since some OSes put crap in some entries. */ - if ( ptab[i].start_lba + ptab[i].length <= self->start_lba || - ptab[i].start_lba >= self->start_lba + self->length ) - continue; - - /* OK, it's a data partition. Is it the one we're looking for? */ - if ( nextpart++ == whichpart ) - return &ptab[i]; - } - } - - /* Scan the extended partitions. */ - for ( i = 0 ; i < 4 ; i++ ) { - if ( ptab[i].ostype != 0x05 && - ptab[i].ostype != 0x0f && ptab[i].ostype != 0x85 ) - continue; /* Skip empty or data partitions */ - - if ( !ptab[i].length ) - continue; - - /* Adjust the offset to account for the extended partition itself */ - if ( root ) - ptab[i].start_lba += root->start_lba; - - /* Sanity check entry: must not extend outside the extended partition. - This is necessary since some OSes put crap in some entries. */ - if ( root ) - if ( ptab[i].start_lba + ptab[i].length <= root->start_lba || - ptab[i].start_lba >= root->start_lba + root->length ) - continue; - - /* Process this partition */ - if ( read_sector(table+SECTOR, ptab[i].start_lba) ) - continue; /* Read error, must be invalid */ - - if ( (found = find_logical_partition(whichpart, table+SECTOR, &ptab[i], - root ? root : &ptab[i])) ) - return found; - } - - /* If we get here, there ain't nothing... */ - return NULL; -} - - -int __start(void) -{ - char *mbr, *boot_sector = NULL; - struct part_entry *partinfo; - char *cmdline = __com32.cs_cmdline; - int hd, drive, whichpart; - static com32sys_t inreg; /* In bss, so zeroed automatically */ - - /* Parse command line */ - while ( isspace(*cmdline) ) - cmdline++; - - hd = 0; - if ( (cmdline[0] == 'h' || cmdline[0] == 'f') && - cmdline[1] == 'd' ) { - hd = cmdline[0] == 'h'; - cmdline += 2; - } - drive = (hd ? 0x80 : 0) | skip_atou(&cmdline); - whichpart = 0; /* Default */ - - if ( isspace(*cmdline) ) { - while ( isspace(*cmdline) ) - cmdline++; - - whichpart = skip_atou(&cmdline); - } - - if ( !(drive & 0x80) && whichpart != 0 ) { - error("Partitions not supported on floppy drives\n"); - goto bail; - } - - /* Divvy up the bounce buffer. To keep things sector- - aligned, give the EBIOS DAPA the first sector, then - the MBR next, and the rest is used for the partition- - chasing stack. */ - dapa = (struct ebios_dapa *)__com32.cs_bounce; - mbr = (char *)__com32.cs_bounce + SECTOR; - - /* Get the MBR */ - if ( get_disk_params(drive) ) { - error("Cannot get disk parameters\n"); - goto bail; - } - - if ( read_sector(mbr, 0) ) { - error("Cannot read MBR\n"); - goto bail; - } - - if ( whichpart == 0 ) { - /* Boot the MBR */ - partinfo = NULL; - boot_sector = mbr; - } else if ( whichpart <= 4 ) { - /* Boot a primary partition */ - partinfo = &((struct part_entry *)(mbr + 0x1be))[whichpart-1]; - if ( partinfo->ostype == 0 ) { - error("Invalid primary partition\n"); - goto bail; - } - } else { - /* Boot a logical partition */ - - nextpart = 5; - partinfo = find_logical_partition(whichpart, mbr, NULL, NULL); - - if ( !partinfo || partinfo->ostype == 0 ) { - error("Requested logical partition not found\n"); - goto bail; - } - } - - /* Do the actual chainloading */ - if ( partinfo ) { - /* Actually read the boot sector */ - /* Pick the first buffer that isn't already in use */ - boot_sector = (char *)(((unsigned long)partinfo + 511) & ~511); - if ( read_sector(boot_sector, partinfo->start_lba) ) { - error("Cannot read boot sector\n"); - goto bail; - } - - /* 0x7BE is the canonical place for the first partition entry. */ - inreg.esi.w[0] = 0x7be; - memcpy((char *)0x7be, partinfo, sizeof(*partinfo)); - } - inreg.eax.w[0] = 0x000d; /* Clean up and chain boot */ - inreg.edx.w[0] = 0; /* Should be 3 for "keeppxe" */ - inreg.edi.l = (uint32_t)boot_sector; - inreg.ecx.l = SECTOR; /* One sector */ - inreg.ebx.b[0] = drive; /* DL = drive no */ - - __com32.cs_intcall(0x22, &inreg, NULL); - - /* If we get here, badness happened */ - error("Chainboot failed!\n"); - -bail: - return 255; -} - - - -- 2.7.4