part: Add support for MBR extended and logical partitions

This commit is contained in:
mintsuki 2020-12-26 20:02:22 +01:00
parent 0daaa565f3
commit 34ddbe6f14
5 changed files with 77 additions and 8 deletions

View File

@ -100,8 +100,8 @@ resource://root/path
The format for `root` changes depending on the resource used. The format for `root` changes depending on the resource used.
A resource can be one of the following: 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. * `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. Omitting the drive is possible; for example: `bios://:2/...`. Omitting the drive makes Limine use 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. * `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`. * `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. * `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.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -103,6 +103,55 @@ struct mbr_entry {
uint32_t sect_count; uint32_t sect_count;
} __attribute__((packed)); } __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) { static int mbr_get_part(struct part *ret, int drive, int partition) {
// Check if actually valid mbr // Check if actually valid mbr
uint16_t hint; uint16_t hint;
@ -110,13 +159,33 @@ static int mbr_get_part(struct part *ret, int drive, int partition) {
if (hint && hint != 0x5a5a) if (hint && hint != 0x5a5a)
return INVALID_TABLE; 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; 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; size_t entry_offset = 0x1be + sizeof(struct mbr_entry) * partition;
int r = disk_read(drive, &entry, entry_offset, sizeof(struct mbr_entry)); int r = disk_read(drive, &entry, entry_offset, sizeof(struct mbr_entry));