vmware-svga/lib/metalkit/image.ld
2009-04-13 07:05:42 +00:00

111 lines
3.2 KiB
Plaintext

/*
* GNU Linker script for assembling a Metalkit binary image.
*
* Notable changes from ld's default behaviour:
*
* - Load address is at the 1MB boundary.
*
* - Our binary begins with a .boot section.
*
* - The end of the data section is padded to a
* 512-byte boundary, to make sure that our disk
* image ends on a sector boundary. (Required by QEMU)
*
* - We calculate a few auxiliary values used by the
* bootloader, which depend on knowing the size of
* the entire binary.
*/
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
OUTPUT_ARCH(i386)
ENTRY(_start)
/*
* Stack starts at the top of the usable portion of the first 1MB, and
* grows downward.
*/
_stack = 0x9fffc;
SECTIONS
{
. = 0x100000;
.text : {
_file_origin = .;
*(.boot);
*(.text .text.*);
}
.data : {
*(.rodata .rodata.* .data .data.*)
_edata = .;
_sector_padding = .;
. = ALIGN(512);
_sector_padding_end = .;
}
.bss : {
__bss_start = .;
*(.bss .bss.*);
}
_end = .;
/DISCARD/ : {
*(.note .note.* .comment .comment.*);
}
}
_bss_size = _end - _edata;
_image_size = _edata - _file_origin;
/*
* Disk geometry. CHS geometry is mostly irrelevant these days, so we
* just pick something that will make fdisk happy. It tries to
* autodetect the disk size by looking at the disk's existing
* partitions, so the easiest way to keep it happy is to align the
* partition to a cylinder boundary.
*
* We'd like to use a floppy-disk-compatible geometry for images that
* are small enough to fit on a 1.44 MB disk, but for larger images we
* need to use a bigger geometry so that our cylinder numbers can fit
* in 10 bits. This larger geometry has 1 megabyte cylinders, so we
* can address 1 GB without breaking the 10 bit boundary.
*/
_geom_large_disk = _image_size >= (2880 * 512);
_geom_sectors_per_head = _geom_large_disk ? 32 : 18;
_geom_heads_per_cylinder = _geom_large_disk ? 64 : 2;
_geom_sectors_per_cylinder = _geom_sectors_per_head * _geom_heads_per_cylinder;
/*
* Partition is just big enough to hold our initialized data, rounded
* up to the nearest cylinder. The "_partition_chs_cylinder" is the
* number of the last cylinder in the partition. Also note that
* sector numbers are 1-based.
*/
_image_sectors = (_image_size + 511) / 512;
_partition_chs_cylinder = _image_sectors / _geom_sectors_per_cylinder;
_partition_blocks = (_partition_chs_cylinder + 1) * _geom_sectors_per_cylinder;
_partition_chs_head = _geom_heads_per_cylinder - 1;
_partition_chs_sector = _geom_sectors_per_head;
/*
* Encode the sector and cylinder bytes in the format expected by MBR
* partition tables.
*/
_partition_chs_cylinder_byte = _partition_chs_cylinder & 0xff;
_partition_chs_sector_byte = _partition_chs_sector |
((_partition_chs_cylinder - _partition_chs_cylinder_byte) >> 2);
/*
* Split up the LDT address into byte-wide chunks, so we can write it
* into the GDT at link time. We can't do this entirely in boot.S,
* because the LDT address isn't contiguous in the GDT.
*/
_ldt_byte0 = (LDT >> 0) & 0xff;
_ldt_byte1 = (LDT >> 8) & 0xff;
_ldt_byte2 = (LDT >> 16) & 0xff;
_ldt_byte3 = (LDT >> 24) & 0xff;