📄 setup.c
字号:
#ident "$Id: setup.c,v 1.40 2004/04/27 06:48:59 hpa Exp $"/* ----------------------------------------------------------------------- * * * Copyright 2001-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. * * ----------------------------------------------------------------------- */#include <stdint.h>#include "e820.h"#include "conio.h"#include "version.h"#include "memdisk.h"/* A pointer to this is stored in the header */const char memdisk_version[] ="MEMDISK " VERSION " " DATE;const char copyright[] = "Copyright " FIRSTYEAR "-" COPYYEAR " H. Peter Anvin";extern const char _binary_memdisk_bin_start[], _binary_memdisk_bin_end[];extern const char _binary_memdisk_bin_size[]; /* Weird, I know */struct memdisk_header { uint16_t int13_offs; uint16_t int15_offs; uint16_t patch_offs; uint16_t total_size;};/* The Disk Parameter Table may be required */typedef union { struct hd_dpt { uint16_t max_cyl; /* Max cylinder */ uint8_t max_head; /* Max head */ uint8_t junk1[5]; /* Obsolete junk, leave at zero */ uint8_t ctrl; /* Control byte */ uint8_t junk2[7]; /* More obsolete junk */ } hd; struct fd_dpt { uint8_t specify1; /* "First specify byte" */ uint8_t specify2; /* "Second specify byte" */ uint8_t delay; /* Delay until motor turn off */ uint8_t sectors; /* Sectors/track */ uint8_t bps; /* Bytes/sector (02h = 512) */ uint8_t isgap; /* Length of intersector gap */ uint8_t dlen; /* Data length (0FFh) */ uint8_t fgap; /* Formatting gap */ uint8_t ffill; /* Format fill byte */ uint8_t settle; /* Head settle time (ms) */ uint8_t mstart; /* Motor start time */ uint8_t _pad1; /* Padding */ uint32_t old_fd_dpt; /* Extension: pointer to old INT 1Eh */ } fd;} dpt_t;struct patch_area { uint32_t diskbuf; uint32_t disksize; uint16_t cmdline_off, cmdline_seg; uint32_t oldint13; uint32_t oldint15; uint16_t olddosmem; uint16_t memint1588; uint16_t cylinders; uint16_t heads; uint32_t sectors; uint32_t mem1mb; uint32_t mem16mb; uint8_t driveno; uint8_t drivetype; uint8_t drivecnt; uint8_t _pad1; uint16_t mystack; uint16_t statusptr; dpt_t dpt;};/* This is the header in the boot sector/setup area */struct setup_header { char cmdline[0x1f1]; uint8_t setup_secs; uint16_t syssize; uint16_t swap_dev; uint16_t ram_size; uint16_t vid_mode; uint16_t root_dev; uint16_t boot_flag; uint16_t jump; char header[4]; uint16_t version; uint32_t realmode_swtch; uint32_t start_sys; uint8_t type_of_loader; uint8_t loadflags; uint16_t setup_move_size; uint32_t code32_start; uint32_t ramdisk_image; uint32_t ramdisk_size; uint32_t bootsect_kludge; uint16_t head_end_ptr; uint16_t pad1; uint32_t cmd_line_ptr; uint32_t initrd_addr_max;};const struct setup_header * const shdr = (struct setup_header *)(LOW_SEG << 4);/* Access to high memory *//* Access to objects in the zero page */static inline voidwrz_8(uint32_t addr, uint8_t data){ *((uint8_t *)addr) = data;}static inline voidwrz_16(uint32_t addr, uint16_t data){ *((uint16_t *)addr) = data;}static inline voidwrz_32(uint32_t addr, uint32_t data){ *((uint32_t *)addr) = data;}static inline uint8_trdz_8(uint32_t addr){ return *((uint8_t *)addr);}static inline uint16_trdz_16(uint32_t addr){ return *((uint16_t *)addr);}static inline uint32_trdz_32(uint32_t addr){ return *((uint32_t *)addr);}/* Addresses in the zero page */#define BIOS_INT13 (0x13*4) /* INT 13h vector */#define BIOS_INT15 (0x15*4) /* INT 15h vector */#define BIOS_INT1E (0x1E*4) /* INT 1Eh vector */#define BIOS_INT40 (0x40*4) /* INT 13h vector */#define BIOS_INT41 (0x41*4) /* INT 41h vector */#define BIOS_INT46 (0x46*4) /* INT 46h vector */#define BIOS_BASEMEM 0x413 /* Amount of DOS memory */#define BIOS_EQUIP 0x410 /* BIOS equipment list */#define BIOS_HD_COUNT 0x475 /* Number of hard drives present *//* * Routine to seek for a command-line item and return a pointer * to the data portion, if present *//* Magic return values */#define CMD_NOTFOUND ((char *)-1) /* Not found */#define CMD_BOOL ((char *)-2) /* Found boolean option */#define CMD_HASDATA(X) ((int)(X) >= 0)const char *getcmditem(const char *what){ const char *p; const char *wp = what; int match = 0; for ( p = shdr->cmdline ; *p ; p++ ) { switch ( match ) { case 0: /* Ground state */ if ( *p == ' ' ) break; wp = what; match = 1; /* Fall through */ case 1: /* Matching */ if ( *wp == '\0' ) { if ( *p == '=' ) return p+1; else if ( *p == ' ' ) return CMD_BOOL; else { match = 2; break; } } if ( *p != *wp++ ) match = 2; break; case 2: /* Mismatch, skip rest of option */ if ( *p == ' ' ) match = 0; /* Next option */ break; } } /* Check for matching string at end of line */ if ( match == 1 && *wp == '\0' ) return CMD_BOOL; return CMD_NOTFOUND;}/* * Check to see if this is a gzip image */#define UNZIP_ALIGN 512extern void _end; /* Symbol signalling end of data */void unzip_if_needed(uint32_t *where_p, uint32_t *size_p){ uint32_t where = *where_p; uint32_t size = *size_p; uint32_t zbytes; uint32_t startrange, endrange; uint32_t gzdatasize, gzwhere; uint32_t orig_crc, offset; uint32_t target = 0; int i, okmem; /* Is it a gzip image? */ if (check_zip ((void *)where, size, &zbytes, &gzdatasize, &orig_crc, &offset) == 0) { if (offset + zbytes > size) { /* Assertion failure; check_zip is supposed to guarantee this never happens. */ puts("internal error: check_zip returned nonsense\n"); die(); } /* Find a good place to put it: search memory ranges in descending order until we find one that is legal and fits */ okmem = 0; for ( i = nranges-1 ; i >= 0 ; i-- ) { /* We can't use > 4G memory (32 bits only.) Truncate to 2^32-1 so we don't have to deal with funny wraparound issues. */ /* Must be memory */ if ( ranges[i].type != 1 ) continue; /* Range start */ if ( ranges[i].start >= 0xFFFFFFFF ) continue; startrange = (uint32_t)ranges[i].start; /* Range end (0 for end means 2^64) */ endrange = ((ranges[i+1].start >= 0xFFFFFFFF || ranges[i+1].start == 0) ? 0xFFFFFFFF : (uint32_t)ranges[i+1].start); /* Make sure we don't overwrite ourselves */ if ( startrange < (uint32_t)&_end ) startrange = (uint32_t)&_end; /* Allow for alignment */ startrange = (ranges[i].start + (UNZIP_ALIGN-1)) & ~(UNZIP_ALIGN-1); /* In case we just killed the whole range... */ if ( startrange >= endrange ) continue; /* Must be large enough... don't rely on gzwhere for this (wraparound) */ if ( endrange-startrange < gzdatasize ) continue; /* This is where the gz image should be put if we put it in this range */ gzwhere = (endrange - gzdatasize) & ~(UNZIP_ALIGN-1); /* Cast to uint64_t just in case we're flush with the top byte */ if ( (uint64_t)where+size >= gzwhere && where < endrange ) { /* Need to move source data to avoid compressed/uncompressed overlap */ uint32_t newwhere; if ( gzwhere-startrange < size ) continue; /* Can't fit both old and new */ newwhere = (gzwhere - size) & ~(UNZIP_ALIGN-1); printf("Moving compressed data from 0x%08x to 0x%08x\n", where, newwhere); /* Our memcpy() is OK, because we always move from a higher address to a lower one */ memcpy((void *)newwhere, (void *)where, size); where = newwhere; } target = gzwhere; okmem = 1; break; } if ( !okmem ) { puts("Not enough memory to decompress image\n"); die(); } printf("gzip image: decompressed addr 0x%08x, len 0x%08x: ", target, gzdatasize); *size_p = gzdatasize; *where_p = (uint32_t)unzip((void *)(where + offset), zbytes, gzdatasize, orig_crc, (void *)target); }}/* * Figure out the "geometry" of the disk in question */struct geometry { uint32_t sectors; /* 512-byte sector count */ uint32_t c, h, s; /* C/H/S geometry */ uint32_t offset; /* Byte offset for disk */ uint8_t type; /* Type byte for INT 13h AH=08h */ uint8_t driveno; /* Drive no */};static const struct geometry geometries[] ={ { 720, 40, 2, 9, 0, 0x01, 0 }, /* 360 K */ { 1440, 80, 2, 9, 0, 0x03, 0 }, /* 720 K*/ { 2400, 80, 2, 15, 0, 0x02, 0 }, /* 1200 K */ { 2880, 80, 2, 18, 0, 0x04, 0 }, /* 1440 K */ { 1680, 80, 2, 21, 0, 0x04, 0 }, /* 1680 K */ { 1722, 82, 2, 21, 0, 0x04, 0 }, /* 1722 K */ { 5760, 80, 2, 36, 0, 0x06, 0 }, /* 2880 K */};#define known_geometries (sizeof(geometries)/sizeof(struct geometry))/* Format of a DOS partition table entry */struct ptab_entry { uint8_t active; uint8_t start_h, start_s, start_c; uint8_t type; uint8_t end_h, end_s, end_c; uint32_t start; uint32_t size;};/* Format of a DOSEMU header */struct dosemu_header { uint8_t magic[7]; /* DOSEMU\0 */ uint32_t h; uint32_t s; uint32_t c; uint32_t offset;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -