diff options
author | hpa <hpa> | 2001-12-10 06:46:18 +0000 |
---|---|---|
committer | hpa <hpa> | 2001-12-10 06:46:18 +0000 |
commit | a47c6d65c1fbab9d821b869fc0bd30ae441f24fc (patch) | |
tree | 5c60a193c3575213d90b1cf6494b9865ee802e01 | |
parent | b4809196e7d8ea83991b0cd51f989e7210b5b5b0 (diff) | |
download | syslinux-a47c6d65c1fbab9d821b869fc0bd30ae441f24fc.tar.gz |
Yet another snapshot. Now we can actually compile the sucker...
-rw-r--r-- | memdisk/Makefile | 26 | ||||
-rw-r--r-- | memdisk/e820.h | 3 | ||||
-rw-r--r-- | memdisk/init.S16 | 150 | ||||
-rw-r--r-- | memdisk/memdisk.asm | 20 | ||||
-rw-r--r-- | memdisk/msetup.c | 157 | ||||
-rw-r--r-- | memdisk/setup.c | 271 |
6 files changed, 462 insertions, 165 deletions
diff --git a/memdisk/Makefile b/memdisk/Makefile index 52b33f71..9e81685c 100644 --- a/memdisk/Makefile +++ b/memdisk/Makefile @@ -12,16 +12,21 @@ ## ----------------------------------------------------------------------- CC = gcc -CFLAGS = -g -O2 -fomit-frame-pointer -march=i386 -malign-functions=0 -malign-jumps=0 -malign-loops=0 +CFLAGS = -g -O2 -fomit-frame-pointer -march=i386 \ + -malign-functions=0 -malign-jumps=0 -malign-loops=0 LDFLAGS = AS = as LD = ld NASM = nasm +OBJCOPY = objcopy -all: e820func.o16 msetup.o16 e820test memdisk.bin +# Important: init.o16 must be first!! +OBJS = init.o16 setup.o16 msetup.o16 e820func.o16 memdisk.o + +all: memdisk e820test clean: - rm -f *.o *.s *.o16 *.s16 *.bin *.lst e820test + rm -f *.o *.s *.o16 *.s16 *.bin *.lst *.elf e820test memdisk %.o16: %.s16 $(AS) -o $@ $< @@ -29,15 +34,30 @@ clean: %.s16: %.s echo '.code16' | cat - $< > $@ +%.s: %.S + $(CC) -x c $(CFLAGS) -Wp,-traditional -E -o $@ $< + +%.s16: %.S16 + $(CC) -x c $(CFLAGS) -Wp,-traditional -E -o $@ $< + %.s: %.c $(CC) $(CFLAGS) -S -o $@ $< +%.i: %.c + $(CC) $(CFLAGS) -E -o $@ $< + %.o: %.c $(CC) $(CFLAGS) -c -o $@ $< %.bin: %.asm $(NASM) -f bin -o $@ -l $*.lst $< +memdisk.elf: $(OBJS) + $(LD) -Ttext 0 -o $@ $^ + +memdisk: memdisk.elf + $(OBJCOPY) -O binary $< $@ + e820test: e820func.o msetup.o e820test.o memdisk.o $(CC) $(LDFLAGS) -o $@ $^ diff --git a/memdisk/e820.h b/memdisk/e820.h index ec261d7f..7f064c43 100644 --- a/memdisk/e820.h +++ b/memdisk/e820.h @@ -26,5 +26,8 @@ struct e820range { extern struct e820range ranges[]; extern int nranges; +extern uint32_t dos_mem, low_mem, high_mem; extern void insertrange(uint64_t, uint64_t, uint32_t); +extern void get_mem(void); +extern void parse_mem(void); diff --git a/memdisk/init.S16 b/memdisk/init.S16 new file mode 100644 index 00000000..0231d8f7 --- /dev/null +++ b/memdisk/init.S16 @@ -0,0 +1,150 @@ +/* $Id$ */ +/* ----------------------------------------------------------------------- * + * + * Copyright 2001 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. + * + * ----------------------------------------------------------------------- */ + +/* + * init.S + * + * memdisk initialization code + * + * This module *MUST* get linked first into the image + */ + + .section ".text", "ax" + .code16 + +/* + * The header derives directly from the Linux kernel and must be first + * in the binary, hence section .init + */ + .org 497 +setup_sects: .byte 0 # Filled in later +root_flags: .word 0 +syssize: .word 0 +swap_dev: .word 0 +ram_size: .word 0 +vid_mode: .word 0 +root_dev: .word 0 +boot_flag: .word 0xAA55 + + .globl _start +_start: + jmp start + +# This is the setup header, and it must start at %cs:2 (old 0x9020:2) + + .ascii "HdrS" # header signature + .word 0x0203 # header version number (>= 0x0105) + # or else old loadlin-1.5 will fail) +realmode_swtch: .word 0, 0 # default_switch, SETUPSEG +start_sys_seg: .word 0 + .word kernel_version # pointing to kernel version string + # above section of header is compatible + # with loadlin-1.5 (header v1.5). + +type_of_loader: .byte 0 # = 0, old one (LILO, Loadlin, + # Bootlin, SYSLX, bootsect...) + # See Documentation/i386/boot.txt for + # assigned ids + +# flags, unused bits must be zero (RFU) bit within loadflags +loadflags: +LOADED_HIGH = 1 # If set, the kernel is loaded high +CAN_USE_HEAP = 0x80 # If set, the loader also has set + # heap_end_ptr to tell how much + # space behind setup.S can be used for + # heap purposes. + # Only the loader knows what is free + + .byte LOADED_HIGH # Dont force the loader to move + # us to 0x90000 + +setup_move_size: .word 0 # Unused + +code32_start: # here loaders can put a different + # start address for 32-bit code. +#ifndef __BIG_KERNEL__ + .long 0x1000 # 0x1000 = default for zImage +#else + .long 0x100000 # 0x100000 = default for big kernel +#endif + +ramdisk_image: .long 0 # address of loaded ramdisk image + # Here the loader puts the 32-bit + # address where it loaded the image. + # This only will be read by the kernel. + +ramdisk_size: .long 0 # its size in bytes + +bootsect_kludge: + .word 0, 0 + +heap_end_ptr: .word 0 # (Header version 0x0201 or later) + # space from here (exclusive) down to + # end of setup code can be used by setup + # for local heap purposes. + +pad1: .word 0 +cmd_line_ptr: .long 0 # (Header version 0x0202 or later) + # If nonzero, a 32-bit pointer + # to the kernel command line. + # The command line should be + # located between the start of + # setup and the end of low + # memory (0xa0000), or it may + # get overwritten before it + # gets read. If this field is + # used, there is no longer + # anything magical about the + # 0x90000 segment; the setup + # can be located anywhere in + # low memory 0x10000 or higher. + +ramdisk_max: .long 0xffffffff # Load ramdisk as high as + # absolutely possible + +/* ------------------- End of setup header --------------------------- */ + +/* + * Canonicalize CS to match the other segments; also, the C + * code uses 32-bit registers to make sure the high part of + * %esp is zero. + */ +start: + .byte 0x66,0x0f,0xb7,0xe4 # movzwl %sp,%esp + pushw %ds + pushw $main + lret + +main: + sti + call setup # Call the C code + # The setup function returns the drive number, + # which should be returned in %dl + movw %ax,%dx + + # If the C code returns, we are good to go, and the + # new boot sector is already loaded + cli + movw $0x7c00,%sp + xorw %si,%si # Not a partition BS - SI <- 0 + movw %si,%ds + movw %si,%es + movw %si,%fs + movw %si,%gs + movw %si,%ss + ljmp $0,$0x7c00 # Entrypoint at 0000:7C00 + + .section ".rodata", "a" +kernel_version: .ascii "MEMDISK ..." + .byte 0 + diff --git a/memdisk/memdisk.asm b/memdisk/memdisk.asm index 46e19236..3c9513dd 100644 --- a/memdisk/memdisk.asm +++ b/memdisk/memdisk.asm @@ -127,8 +127,16 @@ GetDriveType: pop ax ; Drop return address mov ah,[DriveNo] shr ah,7 + pushf or ah,02h ; CF = 0 mov P_AH,ah + popf + jz .floppy + mov ax,[DiskSize] ; For hard disk return the size + mov P_DX,ax + mov ax,[DiskSize+2] + mov P_CX,ax +.floppy: mov [LastStatus],byte 0 ; Success, but AH returns a value jmp short DoneWeird @@ -402,15 +410,12 @@ Mover_dst1: db 0, 0, 0 ; Low 24 bits of target addy db 00h ; Extended access rights Mover_dst2: db 0 ; High 8 bits of source addy +LastStatus db 0 ; Last return status + section .bss alignb 4 PatchArea equ $ ; This gets filled in by the installer -DriveNo resb 1 ; Our drive number -DriveType resb 1 ; Our drive type (floppies) -LastStatus resb 1 ; Last return status - resb 1 ; pad - Cylinders resw 1 ; Cylinder count Heads resw 1 ; Head count Sectors resd 1 ; Sector count (zero-extended) @@ -425,6 +430,11 @@ MemInt1588 resd 1 ; 1MB-65MB memory amount (1K) OldInt13 resd 1 ; INT 13h in chain OldInt15 resd 1 ; INT 15h in chain +OldDosMem resw 1 ; Old position of DOS mem end + +DriveNo resb 1 ; Our drive number +DriveType resb 1 ; Our drive type (floppies) + ; End patch area Stack resd 2 ; Saved SS:ESP on invocation diff --git a/memdisk/msetup.c b/memdisk/msetup.c index 713f368f..c37169be 100644 --- a/memdisk/msetup.c +++ b/memdisk/msetup.c @@ -181,160 +181,3 @@ void parse_mem(void) } } } - -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; -}; -struct patch_area { - uint8_t driveno; - uint8_t drivetype; - uint8_t laststatus; - uint8_t _pad1; - - uint16_t cylinders; - uint16_t heads; - uint32_t sectors; - uint32_t disksize; - uint32_t diskbuf; - - uint32_t e820table; - uint32_t mem1mb; - uint32_t mem16mb; - uint32_t memint1588; - - uint32_t oldint13; - uint32_t oldint15; - uint16_t olddosmem; -}; - -/* Access to objects in the zero page */ -static inline void -wrz_8(uint32_t addr, uint8_t data) -{ - asm volatile("movb %0,%%fs:%1" :: "ri" (data), "m" (*(uint8_t *)addr)); -} -static inline void -wrz_16(uint32_t addr, uint16_t data) -{ - asm volatile("movw %0,%%fs:%1" :: "ri" (data), "m" (*(uint16_t *)addr)); -} -static inline void -wrz_32(uint32_t addr, uint16_t data) -{ - asm volatile("movl %0,%%fs:%1" :: "ri" (data), "m" (*(uint32_t *)addr)); -} -static inline uint8_t -rdz_8(uint32_t addr) -{ - uint8_t data; - asm volatile("movb %%fs:%1,%0" : "=r" (data) : "m" (*(uint8_t *)addr)); - return data; -} -static inline uint16_t -rdz_16(uint32_t addr) -{ - uint16_t data; - asm volatile("movw %%fs:%1,%0" : "=r" (data) : "m" (*(uint16_t *)addr)); - return data; -} -static inline uint8_t -rdz_32(uint32_t addr) -{ - uint32_t data; - asm volatile("movl %%fs:%1,%0" : "=r" (data) : "m" (*(uint32_t *)addr)); - return data; -} - -/* Addresses in the zero page */ -#define BIOS_INT13 (0x13*4) /* INT 13h vector */ -#define BIOS_INT15 (0x15*4) /* INT 13h vector */ -#define BIOS_BASEMEM 0x413 /* Amount of DOS memory */ - -void setup(void) -{ - unsigned int size = (int) &_binary_memdisk_bin_size; - struct memdisk_header *hptr; - struct patch_area *pptr; - uint16_t driverseg; - uint32_t driverptr, driveraddr; - uint8_t driveno = 0; - uint8_t status; - uint16_t exitcode; - - /* Point %fs to the zero page */ - asm volatile("movw %0,%%fs" :: "r" (0)); - - get_mem(); - parse_mem(); - - /* Figure out where it needs to go */ - hptr = (struct memdisk_header *) &_binary_memdisk_bin_start; - pptr = (struct patch_area *)(_binary_memdisk_bin_start + hptr->patch_offs); - - if ( hptr->total_size > dos_mem ) { - /* Badness... */ - } - - pptr->olddosmem = rdz_16(BIOS_BASEMEM); - - driveraddr = dos_mem - hptr->total_size; - driveraddr &= ~0x3FF; - - /* Reserve this range of memory */ - insertrange(driveraddr, dos_mem-driveraddr, 2); - parse_mem(); - - pptr->mem1mb = low_mem >> 10; - pptr->mem16mb = high_mem >> 16; - pptr->memint1588 = (low_mem == 0xf00000) - ? ((high_mem > 0x30ffc00) ? 0xffff : (high_mem >> 10)+0x3c00) - : (low_mem >> 10); - - driverseg = driveraddr >> 4; - driverptr = driverseg << 16; - - pptr->oldint13 = rdz_32(BIOS_INT13); - pptr->oldint15 = rdz_32(BIOS_INT15); - - /* Claim the memory and copy the driver into place */ - wrz_16(BIOS_BASEMEM, dos_mem >> 10); - - asm volatile("pushw %%es ; " - "movw %0,%%es ; " - "rep ; movsl %%ds:(%%si), %%es:(%%di) ; " - "popw %%es" - :: "r" (driverseg), - "c" (size >> 2), - "S" (&_binary_memdisk_bin_start), - "D" (0)); - - /* Install the interrupt handlers */ - wrz_32(BIOS_INT13, driverptr+hptr->int13_offs); - wrz_32(BIOS_INT15, driverptr+hptr->int15_offs); - - /* Reboot into the new "disk" */ - asm volatile("pushw %%es ; " - "xorw %%cx,%%cx ; " - "movw %%cx,%%es ; " - "incw %%cx ; " - "movw $0x0201,%%ax ; " - "movw $0x7c00,%%bx ; " - "int $0x13 ; " - "setc %0 ; " - "popw %%es" - : "=r" (status), "=a" (exitcode) - : "d" ((uint16_t)driveno) - : "ebx", "ecx", "edx", "esi", "edi", "ebp"); - - if ( status ) { - /* Badness... */ - } - - /* On return the assembly code will jump to the boot vector */ -} - diff --git a/memdisk/setup.c b/memdisk/setup.c new file mode 100644 index 00000000..d40f21bb --- /dev/null +++ b/memdisk/setup.c @@ -0,0 +1,271 @@ +#ident "$Id$" +/* ----------------------------------------------------------------------- * + * + * Copyright 2001 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" + +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; +}; + +struct patch_area { + uint16_t cylinders; + uint16_t heads; + uint32_t sectors; + uint32_t disksize; + uint32_t diskbuf; + + uint32_t e820table; + uint32_t mem1mb; + uint32_t mem16mb; + uint32_t memint1588; + + uint32_t oldint13; + uint32_t oldint15; + + uint16_t olddosmem; + + uint8_t driveno; + uint8_t drivetype; +}; + +/* This is the header in the boot sector/setup area */ +struct setup_header { + uint8_t dummy[0x1f1]; /* Boot sector */ + 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 *)0; + +/* Access to objects in the zero page */ +static inline void +wrz_8(uint32_t addr, uint8_t data) +{ + asm volatile("movb %0,%%fs:%1" :: "ri" (data), "m" (*(uint8_t *)addr)); +} +static inline void +wrz_16(uint32_t addr, uint16_t data) +{ + asm volatile("movw %0,%%fs:%1" :: "ri" (data), "m" (*(uint16_t *)addr)); +} +static inline void +wrz_32(uint32_t addr, uint16_t data) +{ + asm volatile("movl %0,%%fs:%1" :: "ri" (data), "m" (*(uint32_t *)addr)); +} +static inline uint8_t +rdz_8(uint32_t addr) +{ + uint8_t data; + asm volatile("movb %%fs:%1,%0" : "=r" (data) : "m" (*(uint8_t *)addr)); + return data; +} +static inline uint16_t +rdz_16(uint32_t addr) +{ + uint16_t data; + asm volatile("movw %%fs:%1,%0" : "=r" (data) : "m" (*(uint16_t *)addr)); + return data; +} +static inline uint8_t +rdz_32(uint32_t addr) +{ + uint32_t data; + asm volatile("movl %%fs:%1,%0" : "=r" (data) : "m" (*(uint32_t *)addr)); + return data; +} + +/* Addresses in the zero page */ +#define BIOS_INT13 (0x13*4) /* INT 13h vector */ +#define BIOS_INT15 (0x15*4) /* INT 13h vector */ +#define BIOS_BASEMEM 0x413 /* Amount of DOS memory */ + +/* + * Figure out the "geometry" of the disk in question + */ +struct geometry { + uint32_t size; /* Size in bytes */ + uint32_t sectors; /* 512-byte sector limit */ + uint32_t c, h, s; /* C/H/S geometry */ + uint8_t type; /* Type byte for INT 13h AH=08h */ + uint8_t driveno; /* Drive no */ +}; + +static const uint32_t image_sizes[] = +{ 360*1024, + 720*1024, + 1200*1024, + 1440*1024, + 2880*1024, + 0 }; +static const struct geometry geometries[] = +{ { 360*1024, 720, 40, 2, 9, 0x01, 0 }, + { 720*1024, 1440, 80, 2, 9, 0x03, 0 }, + { 1200*1024, 2400, 80, 2, 15, 0x02, 0 }, + { 1440*1024, 2880, 80, 2, 18, 0x04, 0 }, + { 2880*1024, 5760, 80, 2, 36, 0x06, 0 } }; +#define known_geometries (sizeof(geometries)/sizeof(struct geometry)) + +const struct geometry *get_disk_image_geometry(uint32_t where, uint32_t size) +{ + static struct geometry hd_geometry; + int i; + + for ( i = 0 ; i < known_geometries ; i++ ) { + if ( size == geometries[i].size ) { + return &geometries[i]; + } + } + + /* No match, must be a hard disk image */ + /* Need to examine the partition table for geometry */ + + /* For now, though, just use a simple standard geometry CHS = Nx16x63 */ + + hd_geometry.size = size & ~0x1FF; + hd_geometry.sectors = size >> 9; + hd_geometry.c = size/(16*63*512); + hd_geometry.h = 16; + hd_geometry.s = 63; + hd_geometry.type = 0; + hd_geometry.driveno = 0x80; /* Hard drive */ + + return &hd_geometry; +} + +/* + * Actual setup routine + * Returns the drive number (which is then passed in %dl to the + * called routine.) + */ +uint32_t setup(void) +{ + unsigned int size = (int) &_binary_memdisk_bin_size; + struct memdisk_header *hptr; + struct patch_area *pptr; + uint16_t driverseg; + uint32_t driverptr, driveraddr; + uint8_t driveno = 0; + uint8_t status; + uint16_t exitcode; + const struct geometry *geometry; + + /* Point %fs to the zero page */ + asm volatile("movw %0,%%fs" :: "r" (0)); + + geometry = get_disk_image_geometry(shdr->ramdisk_image, shdr->ramdisk_size); + + get_mem(); + parse_mem(); + + /* Figure out where it needs to go */ + hptr = (struct memdisk_header *) &_binary_memdisk_bin_start; + pptr = (struct patch_area *)(_binary_memdisk_bin_start + hptr->patch_offs); + + if ( hptr->total_size > dos_mem ) { + /* Badness... */ + } + + pptr->olddosmem = rdz_16(BIOS_BASEMEM); + pptr->driveno = geometry->driveno; + pptr->drivetype = geometry->type; + pptr->cylinders = geometry->c; + pptr->heads = geometry->h; + pptr->sectors = geometry->s; + pptr->disksize = geometry->sectors; + pptr->diskbuf = shdr->ramdisk_image; + + driveraddr = dos_mem - hptr->total_size; + driveraddr &= ~0x3FF; + + /* Reserve this range of memory */ + insertrange(driveraddr, dos_mem-driveraddr, 2); + parse_mem(); + + pptr->mem1mb = low_mem >> 10; + pptr->mem16mb = high_mem >> 16; + pptr->memint1588 = (low_mem == 0xf00000) + ? ((high_mem > 0x30ffc00) ? 0xffff : (high_mem >> 10)+0x3c00) + : (low_mem >> 10); + + driverseg = driveraddr >> 4; + driverptr = driverseg << 16; + + pptr->oldint13 = rdz_32(BIOS_INT13); + pptr->oldint15 = rdz_32(BIOS_INT15); + + /* Claim the memory and copy the driver into place */ + wrz_16(BIOS_BASEMEM, dos_mem >> 10); + + asm volatile("pushw %%es ; " + "movw %0,%%es ; " + "rep ; movsl %%ds:(%%si), %%es:(%%di) ; " + "popw %%es" + :: "r" (driverseg), + "c" (size >> 2), + "S" (&_binary_memdisk_bin_start), + "D" (0)); + + /* Install the interrupt handlers */ + wrz_32(BIOS_INT13, driverptr+hptr->int13_offs); + wrz_32(BIOS_INT15, driverptr+hptr->int15_offs); + + /* Reboot into the new "disk" */ + asm volatile("pushw %%es ; " + "xorw %%cx,%%cx ; " + "movw %%cx,%%es ; " + "incw %%cx ; " + "movw $0x0201,%%ax ; " + "movw $0x7c00,%%bx ; " + "int $0x13 ; " + "setc %0 ; " + "popw %%es" + : "=r" (status), "=a" (exitcode) + : "d" ((uint16_t)driveno) + : "ebx", "ecx", "edx", "esi", "edi", "ebp"); + + if ( status ) { + /* Badness... */ + } + + /* On return the assembly code will jump to the boot vector */ + return driveno; +} |