The kernel boot code now supports the unknown bus/device method to identify the
boot volume. The other (better) methods are now disabled in the boot loader. This fixes bug #241. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@16895 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#define TRACE_DEVICES
|
//#define TRACE_DEVICES
|
||||||
#ifdef TRACE_DEVICES
|
#ifdef TRACE_DEVICES
|
||||||
# define TRACE(x) dprintf x
|
# define TRACE(x) dprintf x
|
||||||
#else
|
#else
|
||||||
@@ -367,6 +367,7 @@ get_next_check_sum_offset(int32 index, off_t maxSize)
|
|||||||
/** Computes a check sum for the specified block.
|
/** Computes a check sum for the specified block.
|
||||||
* The check sum is the sum of all data in that block interpreted as an
|
* The check sum is the sum of all data in that block interpreted as an
|
||||||
* array of uint32 values.
|
* array of uint32 values.
|
||||||
|
* Note, this must use the same method as the one used in kernel/fs/vfs_boot.cpp.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static uint32
|
static uint32
|
||||||
@@ -699,11 +700,21 @@ BIOSDrive::FillIdentifier()
|
|||||||
if (HasParameters()) {
|
if (HasParameters()) {
|
||||||
// try all drive_parameters versions, beginning from the most informative
|
// try all drive_parameters versions, beginning from the most informative
|
||||||
|
|
||||||
|
#if 0
|
||||||
if (fill_disk_identifier_v3(fIdentifier, fParameters) == B_OK)
|
if (fill_disk_identifier_v3(fIdentifier, fParameters) == B_OK)
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
if (fill_disk_identifier_v2(fIdentifier, fParameters) == B_OK)
|
if (fill_disk_identifier_v2(fIdentifier, fParameters) == B_OK)
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
#else
|
||||||
|
// TODO: the above version is the correct one - it's currently
|
||||||
|
// disabled, as the kernel boot code only supports the
|
||||||
|
// UNKNOWN_BUS/UNKNOWN_DEVICE way to find the correct boot
|
||||||
|
// device.
|
||||||
|
if (fill_disk_identifier_v3(fIdentifier, fParameters) != B_OK)
|
||||||
|
fill_disk_identifier_v2(fIdentifier, fParameters);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
// no interesting information, we have to fall back to the default
|
// no interesting information, we have to fall back to the default
|
||||||
// unknown interface/device type identifier
|
// unknown interface/device type identifier
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2005, Axel Dörfler, [email protected].
|
* Copyright 2002-2006, Axel Dörfler, [email protected].
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
|
* Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
|
||||||
@@ -27,11 +27,9 @@
|
|||||||
|
|
||||||
//#define TRACE_VFS
|
//#define TRACE_VFS
|
||||||
#ifdef TRACE_VFS
|
#ifdef TRACE_VFS
|
||||||
# define PRINT(x) dprintf x
|
# define TRACE(x) dprintf x
|
||||||
# define FUNCTION(x) dprintf x
|
|
||||||
#else
|
#else
|
||||||
# define PRINT(x) ;
|
# define TRACE(x) ;
|
||||||
# define FUNCTION(x) ;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -109,10 +107,100 @@ compare_cd_boot(const void *_a, const void *_b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Computes a check sum for the specified block.
|
||||||
|
* The check sum is the sum of all data in that block interpreted as an
|
||||||
|
* array of uint32 values.
|
||||||
|
* Note, this must use the same method as the one used in
|
||||||
|
* boot/platform/bios_ia32/devices.cpp (or similar solutions).
|
||||||
|
*/
|
||||||
|
|
||||||
|
static uint32
|
||||||
|
compute_check_sum(KDiskDevice *device, off_t offset)
|
||||||
|
{
|
||||||
|
char buffer[512];
|
||||||
|
ssize_t bytesRead = read_pos(device->FD(), offset, buffer, sizeof(buffer));
|
||||||
|
if (bytesRead < B_OK)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (bytesRead < (ssize_t)sizeof(buffer))
|
||||||
|
memset(buffer + bytesRead, 0, sizeof(buffer) - bytesRead);
|
||||||
|
|
||||||
|
uint32 *array = (uint32 *)buffer;
|
||||||
|
uint32 sum = 0;
|
||||||
|
|
||||||
|
for (uint32 i = 0; i < (bytesRead + sizeof(uint32) - 1) / sizeof(uint32); i++) {
|
||||||
|
sum += array[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Checks if the device matches the boot device as specified by the
|
||||||
|
* boot loader.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static bool
|
||||||
|
is_boot_device(kernel_args *args, KDiskDevice *device)
|
||||||
|
{
|
||||||
|
disk_identifier &disk = args->boot_disk.identifier;
|
||||||
|
|
||||||
|
TRACE(("boot device: bus %ld, device %ld\n", disk.bus_type,
|
||||||
|
disk.device_type));
|
||||||
|
|
||||||
|
switch (disk.bus_type) {
|
||||||
|
case PCI_BUS:
|
||||||
|
case LEGACY_BUS:
|
||||||
|
// TODO: implement this! (and then enable this feature in the boot loader)
|
||||||
|
// (we need a way to get the device_node of a device, then)
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UNKNOWN_BUS:
|
||||||
|
// nothing to do here
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (disk.device_type) {
|
||||||
|
case UNKNOWN_DEVICE:
|
||||||
|
// test if the size of the device matches
|
||||||
|
if (device->Size() != disk.device.unknown.size)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// check if the check sums match, too
|
||||||
|
for (int32 i = 0; i < NUM_DISK_CHECK_SUMS; i++) {
|
||||||
|
if (disk.device.unknown.check_sums[i].offset == -1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (compute_check_sum(device, disk.device.unknown.check_sums[i].offset)
|
||||||
|
!= disk.device.unknown.check_sums[i].sum)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ATA_DEVICE:
|
||||||
|
case ATAPI_DEVICE:
|
||||||
|
case SCSI_DEVICE:
|
||||||
|
case USB_DEVICE:
|
||||||
|
case FIREWIRE_DEVICE:
|
||||||
|
case FIBRE_DEVICE:
|
||||||
|
// TODO: implement me!
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Make the boot partition (and probably others) available.
|
||||||
|
* The partitions that are a boot candidate a put into the /a partitions
|
||||||
|
* stack. If the user selected a boot device, there is will only be one
|
||||||
|
* entry in this stack; if not, the most likely is put up first.
|
||||||
|
* The boot code should then just try them one by one.
|
||||||
|
*/
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
get_boot_partitions(kernel_args *args, PartitionStack &partitions)
|
get_boot_partitions(kernel_args *args, PartitionStack &partitions)
|
||||||
{
|
{
|
||||||
// make the boot partition (and probably others) available
|
|
||||||
KDiskDeviceManager::CreateDefault();
|
KDiskDeviceManager::CreateDefault();
|
||||||
KDiskDeviceManager *manager = KDiskDeviceManager::Default();
|
KDiskDeviceManager *manager = KDiskDeviceManager::Default();
|
||||||
|
|
||||||
@@ -129,9 +217,6 @@ get_boot_partitions(kernel_args *args, PartitionStack &partitions)
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToDo: do this for real! It will currently only use the partition offset;
|
|
||||||
// it does not yet use the disk_identifier information.
|
|
||||||
|
|
||||||
struct BootPartitionVisitor : KPartitionVisitor {
|
struct BootPartitionVisitor : KPartitionVisitor {
|
||||||
BootPartitionVisitor(kernel_args &args, PartitionStack &stack)
|
BootPartitionVisitor(kernel_args &args, PartitionStack &stack)
|
||||||
: fArgs(args), fPartitions(stack) {}
|
: fArgs(args), fPartitions(stack) {}
|
||||||
@@ -168,6 +253,9 @@ get_boot_partitions(kernel_args *args, PartitionStack &partitions)
|
|||||||
KDiskDevice *device;
|
KDiskDevice *device;
|
||||||
int32 cookie = 0;
|
int32 cookie = 0;
|
||||||
while ((device = manager->NextDevice(&cookie)) != NULL) {
|
while ((device = manager->NextDevice(&cookie)) != NULL) {
|
||||||
|
if (!is_boot_device(args, device))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (device->VisitEachDescendant(&visitor) != NULL)
|
if (device->VisitEachDescendant(&visitor) != NULL)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user