111 lines
3.2 KiB
Plaintext
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;
|