From 0503a73f11795e58d6a850ce15a103b6c8870eef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Wed, 3 Sep 2003 16:28:47 +0000 Subject: [PATCH] Implemented a simple Apple style partitioning scheme add-on. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@4472 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../kernel/partitioning_systems/Jamfile | 1 + .../kernel/partitioning_systems/apple/Jamfile | 15 ++ .../partitioning_systems/apple/apple.cpp | 217 ++++++++++++++++++ .../kernel/partitioning_systems/apple/apple.h | 93 ++++++++ 4 files changed, 326 insertions(+) create mode 100644 src/add-ons/kernel/partitioning_systems/apple/Jamfile create mode 100644 src/add-ons/kernel/partitioning_systems/apple/apple.cpp create mode 100644 src/add-ons/kernel/partitioning_systems/apple/apple.h diff --git a/src/add-ons/kernel/partitioning_systems/Jamfile b/src/add-ons/kernel/partitioning_systems/Jamfile index 5cfae65158..086886762d 100644 --- a/src/add-ons/kernel/partitioning_systems/Jamfile +++ b/src/add-ons/kernel/partitioning_systems/Jamfile @@ -2,3 +2,4 @@ SubDir OBOS_TOP src add-ons kernel partitioning_systems ; SubInclude OBOS_TOP src add-ons kernel partitioning_systems intel ; SubInclude OBOS_TOP src add-ons kernel partitioning_systems amiga ; +SubInclude OBOS_TOP src add-ons kernel partitioning_systems apple ; diff --git a/src/add-ons/kernel/partitioning_systems/apple/Jamfile b/src/add-ons/kernel/partitioning_systems/apple/Jamfile new file mode 100644 index 0000000000..8c7379a9b4 --- /dev/null +++ b/src/add-ons/kernel/partitioning_systems/apple/Jamfile @@ -0,0 +1,15 @@ +SubDir OBOS_TOP src add-ons kernel partitioning_systems apple ; + +UsePrivateHeaders [ FDirName kernel disk_device_manager ] ; +UsePrivateHeaders [ FDirName kernel ] ; +UsePrivateHeaders [ FDirName storage ] ; + +# For now build a userland version only. +Addon apple : userland partitioning_systems : + apple.cpp + ; + +LinkSharedOSLibs apple : + libkernelland_emu.so + libdisk_device_manager.so + ; diff --git a/src/add-ons/kernel/partitioning_systems/apple/apple.cpp b/src/add-ons/kernel/partitioning_systems/apple/apple.cpp new file mode 100644 index 0000000000..cf11978a7f --- /dev/null +++ b/src/add-ons/kernel/partitioning_systems/apple/apple.cpp @@ -0,0 +1,217 @@ +/* +** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ + + +#include "apple.h" + +#include +#include +#ifdef _BOOT_MODE +# include +#else +# include +#endif +#include + +#include +#include + + +#define TRACE_APPLE 0 +#if TRACE_APPLE +# define TRACE(x) dprintf x +#else +# define TRACE(x) ; +#endif + +static const char *kPartitionModuleName = "partitioning_systems/apple/v1"; + +static const char *kApplePartitionTypes[] = { + "partition_map", // the partition map itself + "Driver", // contains a device driver + "Driver43", // the SCSI 4.3 manager + "MFS", // Macintosh File System + "HFS", // Hierarchical File System (HFS/HFS+) + "Unix_SVR2", // UFS + "PRODOS", + "Free", // unused partition + "Scratch", // empty partition + "Driver_ATA", // the device driver for an ATA device + "Driver_ATAPI", // the device driver for an ATAPI device + "Driver43_CD", // an SCSI CD-ROM driver suitable for booting + "FWDriver", // a FireWire driver for the device + "Void", // dummy partition map entry (used to align entries for CD-ROM) + "Patches", + NULL +}; +#if 0 +static const char *kOtherPartitionTypes[] = { + "Be_BFS", // Be's BFS (not specified endian) +}; +#endif + +static status_t +get_next_partition(int fd, apple_driver_descriptor &descriptor, uint32 &cookie, + apple_partition_map &partition) +{ + uint32 block = cookie; + + // find first partition map if this is the first call, + // or else, just load the next block + do { + ssize_t bytesRead = read_pos(fd, (off_t)block * descriptor.BlockSize(), + (void *)&partition, sizeof(apple_partition_map)); + if (bytesRead < (ssize_t)sizeof(apple_partition_map)) + return B_ERROR; + + block++; + } while (cookie == 0 && block < 64 && !partition.HasValidSignature()); + + if (!partition.HasValidSignature()) { + if (cookie) + return B_ENTRY_NOT_FOUND; + + // we searched for the first partition map entry and failed + return B_ERROR; + } + + // the first partition map entry must be of type Apple_partition_map + if (!cookie && (strncmp(partition.type, "Apple_", 6) + || strcmp(partition.type + 6, kApplePartitionTypes[0]))) + return B_ERROR; + + // ToDo: warn about unknown types? + + cookie = block; + return B_OK; +} + + +// #pragma mark - +// Apple public module interface + + +static status_t +apple_std_ops(int32 op, ...) +{ + switch (op) { + case B_MODULE_INIT: + case B_MODULE_UNINIT: + return B_OK; + } + + return B_ERROR; +} + + +static float +apple_identify_partition(int fd, partition_data *partition, void **_cookie) +{ + struct apple_driver_descriptor *descriptor; + uint8 buffer[512]; + + if (read_pos(fd, 0, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) + return B_ERROR; + + descriptor = (apple_driver_descriptor *)buffer; + + if (!descriptor->HasValidSignature()) + return B_ERROR; + + // ToDo: Should probably call get_next_partition() once to know if there + // are any partitions on this disk + + // copy the relevant part of the first block + descriptor = new apple_driver_descriptor(); + memcpy(descriptor, buffer, sizeof(apple_driver_descriptor)); + + *_cookie = (void *)descriptor; + + // ToDo: reevaluate the priority with ISO-9660 and others in mind + // (for CD-ROM only, as far as I can tell) + return 0.5f; +} + + +static status_t +apple_scan_partition(int fd, partition_data *partition, void *_cookie) +{ + TRACE(("apple_scan_partition(cookie = %p)\n", _cookie)); + + apple_driver_descriptor &descriptor = *(apple_driver_descriptor *)_cookie; + + partition->status = B_PARTITION_VALID; + partition->flags |= B_PARTITION_PARTITIONING_SYSTEM + | B_PARTITION_READ_ONLY; + partition->content_size = descriptor.BlockSize() * descriptor.BlockCount(); + + // scan all children + + apple_partition_map partitionMap; + uint32 index = 0, cookie = 0; + status_t status; + + while ((status = get_next_partition(fd, descriptor, cookie, partitionMap)) == B_OK) { + TRACE(("apple: found partition: name = \"%s\", type = \"%s\"\n", + partitionMap.name, partitionMap.type)); + + if ((uint64)partition->offset + partitionMap.Start(descriptor) + + partitionMap.Size(descriptor) > (uint64)partition->size) { + TRACE(("apple: child partition exceeds existing space (%Ld bytes)\n", + partitionMap.Size(descriptor))); + continue; + } + + partition_data *child = create_child_partition(partition->id, index++, -1); + if (child == NULL) { + TRACE(("apple: Creating child at index %ld failed\n", index - 1)); + return B_ERROR; + } + + child->offset = partition->offset + partitionMap.Start(descriptor); + child->size = partitionMap.Size(descriptor); + child->block_size = partition->block_size; + } + + if (status == B_ENTRY_NOT_FOUND) + return B_OK; + + return status; +} + + +static void +apple_free_identify_partition_cookie(partition_data *partition, void *_cookie) +{ + delete (apple_driver_descriptor *)_cookie; +} + + +#ifndef _BOOT_MODE +static partition_module_info sApplePartitionModule = { +#else +partition_module_info gApplePartitionModule = { +#endif + { + kPartitionModuleName, + 0, + apple_std_ops + }, + kPartitionTypeApple, // pretty_name + 0, // flags + + // scanning + apple_identify_partition, // identify_partition + apple_scan_partition, // scan_partition + apple_free_identify_partition_cookie, // free_identify_partition_cookie + NULL, +}; + +#ifndef _BOOT_MODE +partition_module_info *modules[] = { + &sApplePartitionModule, + NULL +}; +#endif diff --git a/src/add-ons/kernel/partitioning_systems/apple/apple.h b/src/add-ons/kernel/partitioning_systems/apple/apple.h new file mode 100644 index 0000000000..2f9ce3bbcf --- /dev/null +++ b/src/add-ons/kernel/partitioning_systems/apple/apple.h @@ -0,0 +1,93 @@ +/* +** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ +#ifndef APPLE_H +#define APPLE_H + + +#include "SupportDefs.h" +#include "ByteOrder.h" + + +enum apple_signature { + kDriverDescriptorSignature = 'ER', + kPartitionMapSignature = 'PM', + kObsoletePartitionMapSignature = 'TS', +}; + + +struct apple_driver_descriptor { + int16 signature; + int16 block_size; + int32 block_count; + int16 type; // reserved + int16 id; // " + int32 data; // " + int16 descriptor_count; + int32 driver_block; + int16 driver_size; + int16 os_type; // operating system type + + int16 BlockSize() { return B_BENDIAN_TO_HOST_INT16(block_size); } + int32 BlockCount() { return B_BENDIAN_TO_HOST_INT32(block_count); } + + bool HasValidSignature() { return B_BENDIAN_TO_HOST_INT16(signature) == kDriverDescriptorSignature; } +}; + +struct apple_partition_map { + int16 signature; + int16 _reserved0; + int32 map_block_count; + int32 start; // in blocks + int32 size; + char name[32]; + char type[32]; + int32 data_start; // in blocks + int32 data_size; + int32 status; + int32 boot_start; + int32 boot_size; + int32 boot_address; + int32 _reserved1; + int32 boot_entry; + int32 _reserved2; + int32 boot_code_checksum; + char processor_type[16]; + + int32 StartBlock() { return B_BENDIAN_TO_HOST_INT32(start); } + int32 BlockCount() { return B_BENDIAN_TO_HOST_INT32(size); } + uint64 Start(apple_driver_descriptor &descriptor) { return StartBlock() * descriptor.BlockSize(); } + uint64 Size(apple_driver_descriptor &descriptor) { return BlockCount() * descriptor.BlockSize(); } + + bool HasValidSignature(); +}; + + +inline bool +apple_partition_map::HasValidSignature() +{ + int16 sig = B_BENDIAN_TO_HOST_INT16(signature); + + return sig == kPartitionMapSignature + || sig == kObsoletePartitionMapSignature; +} + + +enum partition_status { + kPartitionIsValid = 0x00000001, + kPartitionIsAllocated = 0x00000002, + kPartitionIsInUse = 0x00000004, + kPartitionIsBootValid = 0x00000008, + kPartitionIsReadable = 0x00000010, + kPartitionAUXIsWriteable = 0x00000020, // dunno why IsWriteable is here twice... + kPartitionIsBootPIC = 0x00000040, + kPartitionIsWriteable = 0x00000020, + kPartitionIsMounted = 0x40000000, + kPartitionIsStartup = 0x80000000, + kPartitionIsChainCompatible = 0x00000100, + kPartitionIsRealDeviceDriver = 0x00000200, + kPartitionCanChainToNext = 0x00000400, +}; + +#endif /* APPLE_H */