diff --git a/build/jam/packages/Haiku b/build/jam/packages/Haiku index ab98697e6b..275557bec3 100644 --- a/build/jam/packages/Haiku +++ b/build/jam/packages/Haiku @@ -49,7 +49,7 @@ AddFilesToPackage add-ons kernel generic : ata_adapter bios@x86,x86_64 dpc locked_pool mpu401 scsi_periph smbios@x86,x86_64 tty ; AddFilesToPackage add-ons kernel partitioning_systems - : amiga_rdb@m68k apple@ppc efi_gpt intel session ; + : amiga_rdb@m68k apple@ppc sun@sparc efi_gpt intel session ; AddFilesToPackage add-ons kernel interrupt_controllers : openpic@ppc ; AddFilesToPackage add-ons kernel power cpufreq : intel_pstates@x86,x86_64 ; AddFilesToPackage add-ons kernel power cpuidle : intel_cstates@x86,x86_64 ; diff --git a/build/jam/packages/HaikuExtras b/build/jam/packages/HaikuExtras index 2468b347eb..0d5ccd257d 100644 --- a/build/jam/packages/HaikuExtras +++ b/build/jam/packages/HaikuExtras @@ -5,7 +5,7 @@ HaikuPackage $(extrasPackage) ; # kernel modules AddFilesToPackage add-ons kernel partitioning_systems - : amiga_rdb@!m68k apple@!ppc ; + : amiga_rdb@!m68k apple@!ppc sun@!sparc ; AddFilesToPackage add-ons control_look : BeControlLook ; diff --git a/docs/develop/partitioning_systems/sun.txt b/docs/develop/partitioning_systems/sun.txt new file mode 100644 index 0000000000..a280c777d5 --- /dev/null +++ b/docs/develop/partitioning_systems/sun.txt @@ -0,0 +1,72 @@ +Partitioning system for Sun Sparc machines +========================================== + +Infos extracted from [File System Forensic Analysis, Brian Carrier](urn:isbn:0-134-43954-6) +and in particular the [online copy here](https://books.google.fr/books?id=Zpm9CgAAQBAJ&lpg=PT159&ots=6LIQ6blJCF&dq=solaris%20vtoc%20structure&hl=fr&pg=PT159#v=onepage&q=solaris%20vtoc%20structure&f=false), tables 6.9 and 6.10. + +The format is called VTOC (volume table of contents). It is stored at offset 0 +on-disk. All values are big endian. + +Note that the x86 version of Solaris uses a different layout. + +Byte offset|Description +0-127 |ASCII disk label +128-261 |VTOC * +262-263 |Sectors to skip when writing +264-265 |Setors to skip when reading +266-419 |Reserved +420-421 |Disk speed +422-423 |Number of cylinders +424-425 |Alternates per cylinder +426-429 |Reserved +430-431 |Interleave +432-433 |Number of data cylinders +434-435 |Number of alternate cylinders +436-437 |Number of heads +438-439 |Number of sectors per track +440-443 |Reserved +444-451 |Partition 1 disk map +... |More partition disk maps +500-507 |Partition 8 disk map +508-509 |Signature (0xDABE) +510-511 |Checksum + +The VTOC itself: + +0-3 Version +4-11 Volume name +12-13 Number of partitions +14-15 Partition 1 type +16-17 Partition 1 flags +... More partition types and flags +42-45 Partition 8 type and flags +46-57 Boot info +58-59 Reserved +60-63 Signature 0x600DDEEE +64-101 Reserved +102-105 Partition 1 timestamp +... More partition timestamps +130-133 Parittion 8 timestamp + +Partition types (informative): + +0 unassigned +1 /boot +2 / +3 swap +4 /usr +5 entire disk +6 /stand +7 /var +8 /home +9 alternate sector +10 cachefs + +Partition flags: +1 Not mountable +128 read only + +Disk maps: + +0-3 Starting cylinder +4-7 Size (in sectors) diff --git a/src/add-ons/kernel/partitioning_systems/Jamfile b/src/add-ons/kernel/partitioning_systems/Jamfile index 77c050c83e..175954b924 100644 --- a/src/add-ons/kernel/partitioning_systems/Jamfile +++ b/src/add-ons/kernel/partitioning_systems/Jamfile @@ -6,4 +6,5 @@ HaikuSubInclude atari ; HaikuSubInclude gpt ; HaikuSubInclude intel ; HaikuSubInclude session ; +HaikuSubInclude sun ; HaikuSubInclude vmdk ; diff --git a/src/add-ons/kernel/partitioning_systems/sun/Jamfile b/src/add-ons/kernel/partitioning_systems/sun/Jamfile new file mode 100644 index 0000000000..20d9f3804c --- /dev/null +++ b/src/add-ons/kernel/partitioning_systems/sun/Jamfile @@ -0,0 +1,10 @@ +SubDir HAIKU_TOP src add-ons kernel partitioning_systems sun ; + +UsePrivateHeaders [ FDirName kernel disk_device_manager ] ; +UsePrivateHeaders [ FDirName kernel ] ; +UsePrivateHeaders [ FDirName storage ] ; + +KernelAddon sun : + sun.cpp + ; + diff --git a/src/add-ons/kernel/partitioning_systems/sun/sun.cpp b/src/add-ons/kernel/partitioning_systems/sun/sun.cpp new file mode 100644 index 0000000000..9f8bbef516 --- /dev/null +++ b/src/add-ons/kernel/partitioning_systems/sun/sun.cpp @@ -0,0 +1,209 @@ +/* + * Copyright (C) 2020 Adrien Destugues + * + * Distributed under terms of the MIT license. + */ + + +#ifdef _BOOT_MODE +# include +#else +# include +#endif + +#include +#include +#include +#include +#include +#include + + +//#define TRACE_SUN_PARTITION +#ifdef TRACE_SUN_PARTITION +# define TRACE(x) dprintf x +#else +# define TRACE(x) ; +#endif + +#define SUN_PARTITION_MODULE_NAME "partitioning_systems/sun/v1" +#define SUN_PARTITION_NAME "Sun volume table of contents" + + +static uint16_t kMainSignature = 0xDABE; +static uint32_t kVtocSignature = 0x600DDEEE; +static uint32_t kVtocVersion = 1; +static off_t kSectorSize = 512; + + +struct sun_vtoc { + char diskName[128]; + struct { + uint32_t version; + char volumeName[8]; + uint16_t partitionCount; + struct { + uint16_t type; + uint16_t flags; + } partitions[8]; + uint8_t bootinfo[12]; + uint8_t reserved[2]; + uint32_t signature; + uint8_t reserved2[38]; + uint32_t timestamp[8]; + } __attribute__((packed)) vtoc; + uint16_t write_skip; + uint16_t read_skip; + uint8_t reserved[154]; + uint16_t diskSpeed; + uint16_t cylinders; + uint16_t alternates; + uint8_t reserved2[4]; + uint16_t interleave; + uint16_t dataCylinders; + uint16_t alternateCylinders; + uint16_t heads; + uint16_t sectorsPerTrack; + uint8_t reserved3[4]; + struct { + uint32_t startCylinder; + uint32_t sectorCount; + } partitions[8]; + uint16_t signature; + uint16_t checksum; +} __attribute__((packed)); + + +// #pragma mark - +// Sun VTOC public module interface + + +static status_t +sun_std_ops(int32 op, ...) +{ + switch (op) { + case B_MODULE_INIT: + case B_MODULE_UNINIT: + return B_OK; + } + + return B_ERROR; +} + + +static float +sun_identify_partition(int fd, partition_data *partition, void **_cookie) +{ + uint8 buffer[512]; + ssize_t bytesRead = read_pos(fd, 0, buffer, sizeof(buffer)); + sun_vtoc *vtoc = (sun_vtoc *)buffer; + if (bytesRead < (ssize_t)sizeof(buffer)) { + TRACE(("%s: read error: %ld\n", __FUNCTION__, bytesRead)); + return B_ERROR; + } + + if (vtoc->signature == B_HOST_TO_BENDIAN_INT16(kMainSignature) + && vtoc->vtoc.signature == B_HOST_TO_BENDIAN_INT32(kVtocSignature) + && vtoc->vtoc.version == B_HOST_TO_BENDIAN_INT32(kVtocVersion)) { + // TODO verify the checksum + + uint16_t partitionCount + = B_BENDIAN_TO_HOST_INT16(vtoc->vtoc.partitionCount); + TRACE(("Found %d partitions\n", partitionCount)); + + if (partitionCount > 8) + return B_ERROR; + + vtoc = new sun_vtoc(); + memcpy(vtoc, buffer, sizeof(sun_vtoc)); + *_cookie = (void *)vtoc; + + bool hasParent = (get_parent_partition(partition->id) != NULL); + if (!hasParent) + return 0.61; // Larger than iso9660 + else + return 0.3; + } + + return B_ERROR; +} + + +static status_t +sun_scan_partition(int fd, partition_data *partition, void *cookie) +{ + sun_vtoc *vtoc = (sun_vtoc *)cookie; + + partition->status = B_PARTITION_VALID; + partition->flags |= B_PARTITION_PARTITIONING_SYSTEM + | B_PARTITION_READ_ONLY; + partition->content_size = partition->size; + + off_t headCount = B_BENDIAN_TO_HOST_INT16(vtoc->heads); + off_t sectorsPerTrack = B_BENDIAN_TO_HOST_INT16(vtoc->sectorsPerTrack); + off_t cylinderSize = kSectorSize * headCount * sectorsPerTrack; + + TRACE(("%" B_PRIdOFF " heads, %" B_PRIdOFF " sectors, cylindersize %" + B_PRIdOFF "\n", headCount, sectorsPerTrack, cylinderSize)); + + for (int i = 0; i < B_BENDIAN_TO_HOST_INT16(vtoc->vtoc.partitionCount); + i++) { + uint16_t type = B_BENDIAN_TO_HOST_INT16(vtoc->vtoc.partitions[i].type); + // Ignore unused and "whole disk" entries + if (type == 0 || type == 5) + continue; + + off_t start = B_BENDIAN_TO_HOST_INT32( + vtoc->partitions[i].startCylinder) * cylinderSize; + off_t size = B_BENDIAN_TO_HOST_INT32(vtoc->partitions[i].sectorCount) + * kSectorSize; + TRACE(("Part %d type %d start %" B_PRIdOFF " size %" B_PRIdOFF "\n", i, + type, start, size)); + partition_data *child = create_child_partition(partition->id, i, + start, size, -1); + if (child == NULL) { + TRACE(("sun: Creating child at index %d failed\n", i)); + return B_ERROR; + } + child->block_size = partition->block_size; + } + + return B_OK; +} + + +static void +sun_free_identify_partition_cookie(partition_data *partition, void *_cookie) +{ + delete (sun_vtoc *)_cookie; +} + + +#ifndef _BOOT_MODE +static partition_module_info sSunPartitionModule = { +#else +partition_module_info gSunPartitionModule = { +#endif + { + SUN_PARTITION_MODULE_NAME, + 0, + sun_std_ops + }, + "sun", // short_name + SUN_PARTITION_NAME, // pretty_name + 0, // flags + + // scanning + sun_identify_partition, // identify_partition + sun_scan_partition, // scan_partition + sun_free_identify_partition_cookie, // free_identify_partition_cookie + NULL, +// atari_free_partition_content_cookie, // free_partition_content_cookie +}; + +#ifndef _BOOT_MODE +partition_module_info *modules[] = { + &sSunPartitionModule, + NULL +}; +#endif