diff --git a/CONFIG.md b/CONFIG.md index 9d257a2e..b8ebca0b 100644 --- a/CONFIG.md +++ b/CONFIG.md @@ -100,8 +100,8 @@ resource://root/path The format for `root` changes depending on the resource used. A resource can be one of the following: -* `boot` - The `root` is the 1-based decimal value representing the partition on the boot drive. If omitted, the partition containing the configuration file on the boot drive is used. For example: `boot://2/...` will use partition 2 of the boot drive and `boot:///...` will use the partition containing the config file on the boot drive. -* `bios` - The `root` takes the form of `drive:partition`; for example: `bios://3:1/...` would use BIOS drive 3, partition 1. Partitions and BIOS drives are both 1-based. Omitting the drive is possible; for example: `bios://:2/...`. Omitting the drive makes Limine use the boot drive. +* `boot` - The `root` is the 1-based decimal value representing the partition on the boot drive (values of 5+ for MBR logical partitions). If omitted, the partition containing the configuration file on the boot drive is used. For example: `boot://2/...` will use partition 2 of the boot drive and `boot:///...` will use the partition containing the config file on the boot drive. +* `bios` - The `root` takes the form of `drive:partition`; for example: `bios://3:1/...` would use BIOS drive 3, partition 1. Partitions and BIOS drives are both 1-based (partition values of 5+ for MBR logical partitions). Omitting the drive is possible; for example: `bios://:2/...`. Omitting the drive makes Limine use the boot drive. * `guid` - The `root` takes the form of a GUID/UUID, such as `guid://736b5698-5ae1-4dff-be2c-ef8f44a61c52/...`. The GUID is that of either a filesystem, when available, or a GPT partition GUID, when using GPT, in a unified namespace. * `uuid` - Alias of `guid`. * `tftp` - The `root` is the IP address of the tftp server to load the file from. If the root is left empty (`tftp:///...`) the file will be loaded from the server Limine booted from. This resource is only available when booting off PXE. diff --git a/limine-pxe.bin b/limine-pxe.bin index e888346a..038b2693 100644 Binary files a/limine-pxe.bin and b/limine-pxe.bin differ diff --git a/limine.bin b/limine.bin index ef07be3c..2b3f7454 100644 Binary files a/limine.bin and b/limine.bin differ diff --git a/stage2.map b/stage2.map index 2fca87cc..99f8fa9e 100644 Binary files a/stage2.map and b/stage2.map differ diff --git a/stage2/lib/part.c b/stage2/lib/part.c index edb68b2d..1796ceb5 100644 --- a/stage2/lib/part.c +++ b/stage2/lib/part.c @@ -103,6 +103,55 @@ struct mbr_entry { uint32_t sect_count; } __attribute__((packed)); +static int mbr_get_logical_part(struct part *ret, struct part *extended_part, + int drive, int partition) { + struct mbr_entry entry; + + size_t ebr_sector = 0; + + for (int i = 0; i < partition; i++) { + size_t entry_offset = ebr_sector * extended_part->sector_size + 0x1ce; + + int r; + r = part_read(extended_part, &entry, entry_offset, sizeof(struct mbr_entry)); + if (r) + return r; + + if (entry.type != 0x0f && entry.type != 0x05) + return END_OF_TABLE; + + ebr_sector = entry.first_sect; + } + + size_t entry_offset = ebr_sector * extended_part->sector_size + 0x1be; + + int r; + r = part_read(extended_part, &entry, entry_offset, sizeof(struct mbr_entry)); + if (r) + return r; + + if (entry.type == 0) + return NO_PARTITION; + + ret->drive = drive; + ret->partition = partition + 4; + ret->sector_size = disk_get_sector_size(drive); + ret->first_sect = extended_part->first_sect + ebr_sector + entry.first_sect; + ret->sect_count = entry.sect_count; + + struct guid guid; + if (!fs_get_guid(&guid, ret)) { + ret->guid_valid = false; + } else { + ret->guid_valid = true; + ret->guid = guid; + } + + ret->part_guid_valid = false; + + return 0; +} + static int mbr_get_part(struct part *ret, int drive, int partition) { // Check if actually valid mbr uint16_t hint; @@ -110,13 +159,33 @@ static int mbr_get_part(struct part *ret, int drive, int partition) { if (hint && hint != 0x5a5a) return INVALID_TABLE; - if (partition > 3) - return END_OF_TABLE; - - uint32_t disk_signature; - disk_read(drive, &disk_signature, 440, sizeof(uint32_t)); - struct mbr_entry entry; + + if (partition > 3) { + for (int i = 0; i < 4; i++) { + size_t entry_offset = 0x1be + sizeof(struct mbr_entry) * i; + + int r = disk_read(drive, &entry, entry_offset, sizeof(struct mbr_entry)); + if (r) + return r; + + if (entry.type != 0x0f) + continue; + + struct part extended_part; + + extended_part.drive = drive; + extended_part.partition = i; + extended_part.sector_size = disk_get_sector_size(drive); + extended_part.first_sect = entry.first_sect; + extended_part.sect_count = entry.sect_count; + + return mbr_get_logical_part(ret, &extended_part, drive, partition - 4); + } + + return END_OF_TABLE; + } + size_t entry_offset = 0x1be + sizeof(struct mbr_entry) * partition; int r = disk_read(drive, &entry, entry_offset, sizeof(struct mbr_entry));