diff options
author | H. Peter Anvin <hpa@zytor.com> | 2009-03-16 21:42:01 -0700 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2009-03-16 21:42:01 -0700 |
commit | bf6a1aa978ff7a1e85077f85c52ef7324136e01c (patch) | |
tree | 5b5b472c5a40455218d18adb1270e7114a7e6159 /memdisk | |
parent | 7e8ae6da382eb345cb07a836d4230fe9064726c5 (diff) | |
parent | 332a924759efe50e783ad3116ecf17d518dfebe2 (diff) | |
download | syslinux-bf6a1aa978ff7a1e85077f85c52ef7324136e01c.tar.gz |
Merge branch 'master' into memdisk-cd
Diffstat (limited to 'memdisk')
-rw-r--r-- | memdisk/Makefile | 15 | ||||
-rw-r--r-- | memdisk/memdisk.ld | 128 | ||||
-rw-r--r-- | memdisk/setup.c | 262 | ||||
-rw-r--r-- | memdisk/start32.S | 10 |
4 files changed, 314 insertions, 101 deletions
diff --git a/memdisk/Makefile b/memdisk/Makefile index 54b08ba3..d9c16206 100644 --- a/memdisk/Makefile +++ b/memdisk/Makefile @@ -98,8 +98,8 @@ memdisk_%.o: memdisk_%.bin memdisk16.elf: $(OBJS16) $(LD) -Ttext 0 -o $@ $^ -memdisk32.elf: $(OBJS32) - $(LD) -Ttext 0x100000 -o $@ $^ +memdisk32.elf: memdisk.ld $(OBJS32) + $(LD) -o $@ -T $^ %.bin: %.elf $(OBJCOPY) -O binary $< $@ @@ -112,9 +112,12 @@ e820test: e820test.c e820func.c msetup.c .depend: rm -f .depend - for csrc in *.c ; do $(CC) $(INCLUDE) $(CFLAGS) -MM $$csrc >> .depend ; done - for ssrc in *.S ; do $(CC) $(INCLUDE) $(SFLAGS) -MM $$ssrc >> .depend ; done - for nsrc in $(NASMSRC) ; do $(NASM) -DDEPEND $(NINCLUDE) -o `echo $$nsrc | sed -e 's/\.asm/\.bin/'` -M $$nsrc >> .depend ; done + for csrc in *.c ; do $(CC) $(INCLUDE) $(CFLAGS) -MM $$csrc >> .depend ; done ; true + for ssrc in *.S ; do $(CC) $(INCLUDE) $(SFLAGS) -MM $$ssrc >> .depend ; done ; true + for nsrc in $(NASMSRC) ; do \ + ( $(NASM) -DDEPEND $(NINCLUDE) -o \ + `echo $$nsrc | sed -e 's/\.asm/\.bin/'` -M $$nsrc ; \ + echo '' ) >> .depend ; done ; true depend: rm -f .depend @@ -124,4 +127,4 @@ depend: setup.s: ../version # Include dependencies file -include .depend +-include .depend diff --git a/memdisk/memdisk.ld b/memdisk/memdisk.ld new file mode 100644 index 00000000..5b833c2a --- /dev/null +++ b/memdisk/memdisk.ld @@ -0,0 +1,128 @@ +/* + * Linker script for MEMDISK + */ + +/* Script for -z combreloc: combine and sort reloc sections */ +OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") +OUTPUT_ARCH(i386) +EXTERN(_start) +ENTRY(_start) +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = 0x100000; + PROVIDE (__executable_start = .); + + .init : + { + KEEP (*(.init)) + } =0x90909090 + .text : + { + *(.text .stub .text.* .gnu.linkonce.t.*) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + } =0x90909090 + .fini : + { + KEEP (*(.fini)) + } =0x90909090 + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } + .rodata1 : { *(.rodata1) } + + /* Ensure the __preinit_array_start label is properly aligned. We + could instead move the label definition inside the section, but + the linker would then create the section even if it turns out to + be empty, which isn't pretty. */ + . = ALIGN(4); + PROVIDE (__preinit_array_start = .); + .preinit_array : { *(.preinit_array) } + PROVIDE (__preinit_array_end = .); + PROVIDE (__init_array_start = .); + .init_array : { *(.init_array) } + PROVIDE (__init_array_end = .); + PROVIDE (__fini_array_start = .); + .fini_array : { *(.fini_array) } + PROVIDE (__fini_array_end = .); + PROVIDE (__ctors_start = .); + .ctors : + { + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } + PROVIDE (__ctors_end = .); + PROVIDE (__dtors_start = .); + .dtors : + { + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } + PROVIDE (__dtors_end = .); + + /* Adjust the address for the data segment. Avoid mixing code and + data within same 128-byte chunk. */ + . = ALIGN(128); + + .data : + { + *(.data .data.* .gnu.linkonce.d.*) + SORT(CONSTRUCTORS) + } + .data1 : { *(.data1) } + _edata = .; + PROVIDE (edata = .); + . = ALIGN(16); + .bss : + { + __bss_start = .; + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. */ + . = ALIGN(4); + __bss_end = .; + } + _end = .; + PROVIDE (end = .); + + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /DISCARD/ : { *(.note.GNU-stack) } +} diff --git a/memdisk/setup.c b/memdisk/setup.c index bdc60868..b492b0d2 100644 --- a/memdisk/setup.c +++ b/memdisk/setup.c @@ -1,6 +1,6 @@ /* ----------------------------------------------------------------------- * * - * Copyright 2001-2008 H. Peter Anvin - All Rights Reserved + * Copyright 2001-2009 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 @@ -383,7 +383,49 @@ struct ptab_entry { uint8_t end_h, end_s, end_c; uint32_t start; uint32_t size; -}; +} __attribute__((packed)); + +/* Format of a FAT filesystem superblock */ +struct fat_extra { + uint8_t bs_drvnum; + uint8_t bs_resv1; + uint8_t bs_bootsig; + uint32_t bs_volid; + char bs_vollab[11]; + char bs_filsystype[8]; +} __attribute__((packed)); +struct fat_super { + uint8_t bs_jmpboot[3]; + char bs_oemname[8]; + uint16_t bpb_bytspersec; + uint8_t bpb_secperclus; + uint16_t bpb_rsvdseccnt; + uint8_t bpb_numfats; + uint16_t bpb_rootentcnt; + uint16_t bpb_totsec16; + uint8_t bpb_media; + uint16_t bpb_fatsz16; + uint16_t bpb_secpertrk; + uint16_t bpb_numheads; + uint32_t bpb_hiddsec; + uint32_t bpb_totsec32; + union { + struct { + struct fat_extra extra; + } fat16; + struct { + uint32_t bpb_fatsz32; + uint16_t bpb_extflags; + uint16_t bpb_fsver; + uint32_t bpb_rootclus; + uint16_t bpb_fsinfo; + uint16_t bpb_bkbootsec; + char bpb_reserved[12]; + /* Clever, eh? Same fields, different offset... */ + struct fat_extra extra; + } fat32 __attribute__((packed)); + } x; +} __attribute__((packed)); /* Format of a DOSEMU header */ struct dosemu_header { @@ -400,13 +442,10 @@ struct dosemu_header { const struct geometry *get_disk_image_geometry(uint32_t where, uint32_t size) { static struct geometry hd_geometry; - struct ptab_entry ptab[4]; /* Partition table buffer */ struct dosemu_header dosemu; - unsigned int sectors, v; - unsigned int max_c, max_h, max_s; - unsigned int c, h, s, offset; + unsigned int sectors, xsectors, v; + unsigned int offset; int i; - int drive_specified; const char *p; printf("command line: %s\n", shdr->cmdline); @@ -415,54 +454,7 @@ const struct geometry *get_disk_image_geometry(uint32_t where, uint32_t size) if ( CMD_HASDATA(p = getcmditem("offset")) && (v = atou(p)) ) offset = v; - sectors = (size-offset) >> 9; - - if (sectors < 4096*2) { - int ok = 0; - unsigned int xsectors = sectors; - - while (!ok) { - /* Assume it's a floppy drive, guess a geometry */ - unsigned int type, track; - - if (xsectors < 320*2) { - c = 40; h = 1; type = 1; - } else if (xsectors < 640*2) { - c = 40; h = 2; type = 1; - } else if (xsectors < 1200*2) { - c = 80; h = 2; type = 3; - } else if (xsectors < 1440*2) { - c = 80; h = 2; type = 2; - } else if (xsectors < 2880*2) { - c = 80; h = 2; type = 4; - } else { - c = 80; h = 2; type = 6; - } - track = c*h; - while (c < 256) { - s = xsectors/track; - if (s < 63 && (xsectors % track) == 0) { - ok = 1; - break; - } - c++; - track += h; - } - if (ok) { - hd_geometry.driveno = 0; - hd_geometry.c = c; - hd_geometry.h = h; - hd_geometry.s = s; - } else { - /* No valid floppy geometry, fake it by simulating broken - sectors at the end of the image... */ - xsectors++; - } - } - } else { - /* Hard disk */ - hd_geometry.driveno = 0x80; - } + sectors = xsectors = (size-offset) >> 9; hd_geometry.sectors = sectors; hd_geometry.offset = offset; @@ -487,51 +479,133 @@ const struct geometry *get_disk_image_geometry(uint32_t where, uint32_t size) if ( CMD_HASDATA(p = getcmditem("s")) && (v = atou(p)) ) hd_geometry.s = v; + if ( !hd_geometry.h || !hd_geometry.s ) { + int h, s, max_h, max_s; + + max_h = hd_geometry.h; + max_s = hd_geometry.s; + + if (!(max_h|max_s)) { + /* Look for a FAT superblock and if we find something that looks + enough like one, use geometry from that. This takes care of + megafloppy images and unpartitioned hard disks. */ + const struct fat_extra *extra = NULL; + const struct fat_super *fs = (const struct fat_super *) + ((char *)where+hd_geometry.offset); + + if ((fs->bpb_media == 0xf0 || fs->bpb_media >= 0xf8) && + (fs->bs_jmpboot[0] == 0xe9 || fs->bs_jmpboot[0] == 0xeb) && + fs->bpb_bytspersec == 512 && + fs->bpb_numheads >= 1 && fs->bpb_numheads <= 256 && + fs->bpb_secpertrk >= 1 && fs->bpb_secpertrk <= 63) { + extra = fs->bpb_fatsz16 ? &fs->x.fat16.extra : &fs->x.fat32.extra; + if (!(extra->bs_bootsig == 0x29 && + extra->bs_filsystype[0] == 'F' && + extra->bs_filsystype[1] == 'A' && + extra->bs_filsystype[2] == 'T')) + extra = NULL; + } + if (extra) { + hd_geometry.driveno = extra->bs_drvnum & 0x80; + max_h = fs->bpb_numheads; + max_s = fs->bpb_secpertrk; + } + } + + if (!(max_h|max_s)) { + /* No FAT filesystem found to steal geometry from... */ + if (sectors < 4096*2) { + int ok = 0; + unsigned int xsectors = sectors; + + hd_geometry.driveno = 0; /* Assume floppy */ + + while (!ok) { + /* Assume it's a floppy drive, guess a geometry */ + unsigned int type, track; + int c, h, s; + + if (xsectors < 320*2) { + c = 40; h = 1; type = 1; + } else if (xsectors < 640*2) { + c = 40; h = 2; type = 1; + } else if (xsectors < 1200*2) { + c = 80; h = 2; type = 3; + } else if (xsectors < 1440*2) { + c = 80; h = 2; type = 2; + } else if (xsectors < 2880*2) { + c = 80; h = 2; type = 4; + } else { + c = 80; h = 2; type = 6; + } + track = c*h; + while (c < 256) { + s = xsectors/track; + if (s < 63 && (xsectors % track) == 0) { + ok = 1; + break; + } + c++; + track += h; + } + if (ok) { + max_h = h; + max_s = s; + } else { + /* No valid floppy geometry, fake it by simulating broken + sectors at the end of the image... */ + xsectors++; + } + } + } else { + /* Assume it is a hard disk image and scan for a partition table */ + const struct ptab_entry *ptab = (const struct ptab_entry *) + ((char *)where+hd_geometry.offset+(512-2-4*16)); + + hd_geometry.driveno = 0x80; /* Assume hard disk */ + + if (*(uint16_t *)((char *)where+512) == 0xaa55) + for ( i = 0 ; i < 4 ; i++ ) { + if ( ptab[i].type && !(ptab[i].active & 0x7f) ) { + s = (ptab[i].start_s & 0x3f); + h = ptab[i].start_h + 1; + + if ( max_h < h ) max_h = h; + if ( max_s < s ) max_s = s; + + s = (ptab[i].end_s & 0x3f); + h = ptab[i].end_h + 1; + + if ( max_h < h ) max_h = h; + if ( max_s < s ) max_s = s; + } + } + } + } + + if (!max_h) + max_h = xsectors > 2097152 ? 255 : 64; + if (!max_s) + max_s = xsectors > 2097152 ? 63 : 32; + + hd_geometry.h = max_h; + hd_geometry.s = max_s; + } + + if ( !hd_geometry.c ) + hd_geometry.c = xsectors/(hd_geometry.h*hd_geometry.s); + if ( (p = getcmditem("floppy")) != CMD_NOTFOUND ) { hd_geometry.driveno = CMD_HASDATA(p) ? atou(p) & 0x7f : 0; - if ( hd_geometry.type == 0 ) - hd_geometry.type = 0x10; /* ATAPI floppy, e.g. LS-120 */ - drive_specified = 1; } else if ( (p = getcmditem("harddisk")) != CMD_NOTFOUND ) { hd_geometry.driveno = CMD_HASDATA(p) ? atou(p) | 0x80 : 0x80; - hd_geometry.type = 0; - drive_specified = 1; } - if ( (hd_geometry.c == 0) || (hd_geometry.h == 0) || - (hd_geometry.s == 0) ) { - /* Hard disk image, need to examine the partition table for geometry */ - memcpy(&ptab, (char *)where+hd_geometry.offset+(512-2-4*16), sizeof ptab); - - max_c = max_h = 0; max_s = 1; - for ( i = 0 ; i < 4 ; i++ ) { - if ( ptab[i].type ) { - c = ptab[i].start_c + (ptab[i].start_s >> 6); - s = (ptab[i].start_s & 0x3f); - h = ptab[i].start_h; - - if ( max_c < c ) max_c = c; - if ( max_h < h ) max_h = h; - if ( max_s < s ) max_s = s; - - c = ptab[i].end_c + (ptab[i].end_s >> 6); - s = (ptab[i].end_s & 0x3f); - h = ptab[i].end_h; - - if ( max_c < c ) max_c = c; - if ( max_h < h ) max_h = h; - if ( max_s < s ) max_s = s; - } - } - - max_c++; max_h++; /* Convert to count (1-based) */ - - if ( !hd_geometry.h ) - hd_geometry.h = max_h; - if ( !hd_geometry.s ) - hd_geometry.s = max_s; - if ( !hd_geometry.c ) - hd_geometry.c = sectors/(hd_geometry.h*hd_geometry.s); + if (hd_geometry.driveno & 0x80) { + hd_geometry.type = 0; /* Type = hard disk */ + } else { + if (hd_geometry.type == 0) + hd_geometry.type = 0x10; /* ATAPI floppy, e.g. LS-120 */ } if ( (size-hd_geometry.offset) & 0x1ff ) { diff --git a/memdisk/start32.S b/memdisk/start32.S index ee89b71d..073d049c 100644 --- a/memdisk/start32.S +++ b/memdisk/start32.S @@ -2,7 +2,15 @@ # Simple stub to get us to the right point in the 32-bit code; # this module must be linked first # - .text + .section ".init", "ax" .globl _start _start: + /* Zero the bss */ + cld + movl $__bss_start, %edi + movl $__bss_end, %ecx + subl %edi, %ecx + xorl %eax, %eax + shrl $2, %ecx + rep ; stosl jmp setup |