diff --git a/headers/private/kernel/boot/platform.h b/headers/private/kernel/boot/platform.h index c30fcff9c2..146edb3936 100644 --- a/headers/private/kernel/boot/platform.h +++ b/headers/private/kernel/boot/platform.h @@ -59,8 +59,8 @@ namespace boot { extern status_t platform_add_boot_device(struct stage2_args *args, NodeList *devicesList); extern status_t platform_add_block_devices(struct stage2_args *args, NodeList *devicesList); -extern status_t platform_get_boot_partition(struct stage2_args *args, Node *bootDevice, - NodeList *partitions, boot::Partition **_partition); +extern status_t platform_get_boot_partitions(struct stage2_args *args, Node *bootDevice, + NodeList *partitions, NodeList *bootPartitions); extern status_t platform_register_boot_device(Node *device); extern void platform_cleanup_devices(); diff --git a/src/system/boot/loader/vfs.cpp b/src/system/boot/loader/vfs.cpp index 403878b063..e724f123c3 100644 --- a/src/system/boot/loader/vfs.cpp +++ b/src/system/boot/loader/vfs.cpp @@ -659,28 +659,33 @@ get_boot_file_system(stage2_args* args, BootVolume& _bootVolume) if (error != B_OK) continue; - Partition *partition; - error = platform_get_boot_partition(args, device, &gPartitions, &partition); + NodeList bootPartitions; + error = platform_get_boot_partitions(args, device, &gPartitions, &bootPartitions); if (error != B_OK) continue; - Directory *fileSystem; - error = partition->Mount(&fileSystem, true); - if (error != B_OK) { - // this partition doesn't contain any known file system; we - // don't need it anymore - gPartitions.Remove(partition); - delete partition; - continue; + NodeIterator partitionIterator = bootPartitions.GetIterator(); + while (partitionIterator.HasNext()) { + Partition *partition = (Partition*)partitionIterator.Next(); + + Directory *fileSystem; + error = partition->Mount(&fileSystem, true); + if (error != B_OK) { + // this partition doesn't contain any known file system; we + // don't need it anymore + gPartitions.Remove(partition); + delete partition; + continue; + } + + // init the BootVolume + error = _bootVolume.SetTo(fileSystem); + if (error != B_OK) + continue; + + sBootDevice = device; + return B_OK; } - - // init the BootVolume - error = _bootVolume.SetTo(fileSystem); - if (error != B_OK) - continue; - - sBootDevice = device; - return B_OK; } return B_ERROR; diff --git a/src/system/boot/platform/amiga_m68k/devices.cpp b/src/system/boot/platform/amiga_m68k/devices.cpp index c6edd40590..ef33682aff 100644 --- a/src/system/boot/platform/amiga_m68k/devices.cpp +++ b/src/system/boot/platform/amiga_m68k/devices.cpp @@ -168,8 +168,8 @@ platform_add_boot_device(struct stage2_args *args, NodeList *devicesList) status_t -platform_get_boot_partition(struct stage2_args *args, Node *bootDevice, - NodeList *list, boot::Partition **_partition) +platform_get_boot_partitions(struct stage2_args *args, Node *bootDevice, + NodeList *list, NodeList *partitions) { //TODO diff --git a/src/system/boot/platform/atari_m68k/devices.cpp b/src/system/boot/platform/atari_m68k/devices.cpp index 6f9d95cc5d..5738e94369 100644 --- a/src/system/boot/platform/atari_m68k/devices.cpp +++ b/src/system/boot/platform/atari_m68k/devices.cpp @@ -1189,8 +1189,8 @@ platform_add_boot_device(struct stage2_args *args, NodeList *devicesList) status_t -platform_get_boot_partition(struct stage2_args *args, Node *bootDevice, - NodeList *list, boot::Partition **_partition) +platform_get_boot_partitions(struct stage2_args *args, Node *bootDevice, + NodeList *list, NodeList *partitionList) { BlockHandle *drive = static_cast(bootDevice); off_t offset = (off_t)gBootPartitionOffset * drive->BlockSize(); @@ -1205,7 +1205,7 @@ platform_get_boot_partition(struct stage2_args *args, Node *bootDevice, // offset as reported by the BFS boot block if (offset >= partition->offset && offset < partition->offset + partition->size) { - *_partition = partition; + partitionList->Insert(partition); return B_OK; } } diff --git a/src/system/boot/platform/bios_ia32/devices.cpp b/src/system/boot/platform/bios_ia32/devices.cpp index d06798226a..35a1b03d17 100644 --- a/src/system/boot/platform/bios_ia32/devices.cpp +++ b/src/system/boot/platform/bios_ia32/devices.cpp @@ -877,8 +877,8 @@ platform_add_boot_device(struct stage2_args *args, NodeList *devicesList) status_t -platform_get_boot_partition(struct stage2_args *args, Node *bootDevice, - NodeList *list, boot::Partition **_partition) +platform_get_boot_partitions(struct stage2_args *args, Node *bootDevice, + NodeList *list, NodeList *bootList) { BIOSDrive *drive = static_cast(bootDevice); off_t offset = (off_t)gBootPartitionOffset * drive->BlockSize(); @@ -893,7 +893,7 @@ platform_get_boot_partition(struct stage2_args *args, Node *bootDevice, // offset as reported by the BFS boot block if (offset >= partition->offset && offset < partition->offset + partition->size) { - *_partition = partition; + bootList->Insert(partition); return B_OK; } } diff --git a/src/system/boot/platform/efi/devices.cpp b/src/system/boot/platform/efi/devices.cpp index 348ec1437d..18c7180562 100644 --- a/src/system/boot/platform/efi/devices.cpp +++ b/src/system/boot/platform/efi/devices.cpp @@ -8,9 +8,14 @@ #include #include +#include "Header.h" + #include "efi_platform.h" #include +#include "gpt.h" +#include "gpt_known_guids.h" + //#define TRACE_DEVICES #ifdef TRACE_DEVICES @@ -121,6 +126,53 @@ compute_check_sum(Node *device, off_t offset) } +static bool +device_contains_partition(EfiDevice *device, boot::Partition *partition) +{ + EFI::Header *header = (EFI::Header*)partition->content_cookie; + if (header != NULL && header->InitCheck() == B_OK) { + // check if device is GPT, and contains partition entry + uint32 blockSize = device->BlockSize(); + gpt_table_header *deviceHeader = + (gpt_table_header*)malloc(blockSize); + ssize_t bytesRead = device->ReadAt(NULL, blockSize, deviceHeader, + blockSize); + if (bytesRead != blockSize) + return false; + + if (memcmp(deviceHeader, &header->TableHeader(), + sizeof(gpt_table_header)) != 0) + return false; + + // partition->cookie == int partition entry index + uint32 index = (uint32)(addr_t)partition->cookie; + uint32 size = sizeof(gpt_partition_entry) * (index + 1); + gpt_partition_entry *entries = (gpt_partition_entry*)malloc(size); + bytesRead = device->ReadAt(NULL, + deviceHeader->entries_block * blockSize, entries, size); + if (bytesRead != size) + return false; + + if (memcmp(&entries[index], &header->EntryAt(index), + sizeof(gpt_partition_entry)) != 0) + return false; + + for (size_t i = 0; i < sizeof(kTypeMap) / sizeof(struct type_map); ++i) + if (strcmp(kTypeMap[i].type, BFS_NAME) == 0) + if (kTypeMap[i].guid == header->EntryAt(index).partition_type) + return true; + + // Our partition has an EFI header, but we couldn't find one, so bail + return false; + } + + if ((partition->offset + partition->size) <= device->Size()) + return true; + + return false; +} + + status_t platform_add_boot_device(struct stage2_args *args, NodeList *devicesList) { @@ -176,6 +228,7 @@ platform_add_boot_device(struct stage2_args *args, NodeList *devicesList) return devicesList->Count() > 0 ? B_OK : B_ENTRY_NOT_FOUND; } + status_t platform_add_block_devices(struct stage2_args *args, NodeList *devicesList) { @@ -185,13 +238,21 @@ platform_add_block_devices(struct stage2_args *args, NodeList *devicesList) return B_ENTRY_NOT_FOUND; } + status_t -platform_get_boot_partition(struct stage2_args *args, Node *bootDevice, - NodeList *partitions, boot::Partition **_partition) +platform_get_boot_partitions(struct stage2_args *args, Node *bootDevice, + NodeList *partitions, NodeList *bootPartitions) { - TRACE("%s: called\n", __func__); - *_partition = (boot::Partition*)partitions->GetIterator().Next(); - return *_partition != NULL ? B_OK : B_ENTRY_NOT_FOUND; + NodeIterator iterator = partitions->GetIterator(); + boot::Partition *partition = NULL; + while ((partition = (boot::Partition*)iterator.Next()) != NULL) { + if (device_contains_partition((EfiDevice*)bootDevice, partition)) { + iterator.Remove(); + bootPartitions->Insert(partition); + } + } + + return bootPartitions->Count() > 0 ? B_OK : B_ENTRY_NOT_FOUND; } @@ -200,7 +261,6 @@ platform_register_boot_device(Node *device) { TRACE("%s: called\n", __func__); - EfiDevice *efiDevice = (EfiDevice *)device; disk_identifier identifier; identifier.bus_type = UNKNOWN_BUS; diff --git a/src/system/boot/platform/openfirmware/devices.cpp b/src/system/boot/platform/openfirmware/devices.cpp index e177f0e86b..c46267604d 100644 --- a/src/system/boot/platform/openfirmware/devices.cpp +++ b/src/system/boot/platform/openfirmware/devices.cpp @@ -117,14 +117,14 @@ platform_add_boot_device(struct stage2_args *args, NodeList *devicesList) status_t -platform_get_boot_partition(struct stage2_args *args, Node *device, - NodeList *list, boot::Partition **_partition) +platform_get_boot_partitions(struct stage2_args *args, Node *device, + NodeList *list, NodeList *partitionList) { NodeIterator iterator = list->GetIterator(); boot::Partition *partition = NULL; while ((partition = (boot::Partition *)iterator.Next()) != NULL) { // ToDo: just take the first partition for now - *_partition = partition; + partitionList->Insert(partition); return B_OK; } diff --git a/src/system/boot/platform/pxe_ia32/devices.cpp b/src/system/boot/platform/pxe_ia32/devices.cpp index 2ffbcff042..696bf77d2e 100644 --- a/src/system/boot/platform/pxe_ia32/devices.cpp +++ b/src/system/boot/platform/pxe_ia32/devices.cpp @@ -118,15 +118,15 @@ platform_add_boot_device(struct stage2_args *args, NodeList *devicesList) status_t -platform_get_boot_partition(struct stage2_args *args, Node *device, - NodeList *list, boot::Partition **_partition) +platform_get_boot_partitions(struct stage2_args *args, Node *device, + NodeList *list, NodeList *partitionList) { TRACE("platform_get_boot_partition\n"); NodeIterator iterator = list->GetIterator(); boot::Partition *partition = NULL; while ((partition = (boot::Partition *)iterator.Next()) != NULL) { // ToDo: just take the first partition for now - *_partition = partition; + partitionList->Insert(partition); return B_OK; } diff --git a/src/system/boot/platform/u-boot/devices.cpp b/src/system/boot/platform/u-boot/devices.cpp index 140ed1e70a..aaf5206d1b 100644 --- a/src/system/boot/platform/u-boot/devices.cpp +++ b/src/system/boot/platform/u-boot/devices.cpp @@ -48,8 +48,8 @@ platform_add_boot_device(struct stage2_args *args, NodeList *devicesList) status_t -platform_get_boot_partition(struct stage2_args *args, Node *device, - NodeList *list, boot::Partition **_partition) +platform_get_boot_partitions(struct stage2_args *args, Node *device, + NodeList *list, NodeList *partitionList) { TRACE("platform_get_boot_partition\n"); @@ -57,7 +57,7 @@ platform_get_boot_partition(struct stage2_args *args, Node *device, boot::Partition *partition = NULL; while ((partition = (boot::Partition *)iterator.Next()) != NULL) { // ToDo: just take the first partition for now - *_partition = partition; + partitionList->Insert(partition); return B_OK; }