/* * 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