summaryrefslogtreecommitdiff
path: root/memdisk
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2009-03-16 21:42:01 -0700
committerH. Peter Anvin <hpa@zytor.com>2009-03-16 21:42:01 -0700
commitbf6a1aa978ff7a1e85077f85c52ef7324136e01c (patch)
tree5b5b472c5a40455218d18adb1270e7114a7e6159 /memdisk
parent7e8ae6da382eb345cb07a836d4230fe9064726c5 (diff)
parent332a924759efe50e783ad3116ecf17d518dfebe2 (diff)
downloadsyslinux-bf6a1aa978ff7a1e85077f85c52ef7324136e01c.tar.gz
Merge branch 'master' into memdisk-cd
Diffstat (limited to 'memdisk')
-rw-r--r--memdisk/Makefile15
-rw-r--r--memdisk/memdisk.ld128
-rw-r--r--memdisk/setup.c262
-rw-r--r--memdisk/start32.S10
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