* Copyright (C) 2020 Adrien Destugues <pulkomandy@pulkomandy.tk>
*
* Distributed under terms of the MIT license.
*/
#ifdef _BOOT_MODE
# include <boot/partitions.h>
#else
# include <DiskDeviceTypes.h>
#endif
#include <ByteOrder.h>
#include <ddm_modules.h>
#include <util/kernel_cpp.h>
#include <KernelExport.h>
#include <stdint.h>
#include <string.h>
#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));
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)) {
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;
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);
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",
SUN_PARTITION_NAME,
0,
sun_identify_partition,
sun_scan_partition,
sun_free_identify_partition_cookie,
NULL,
};
#ifndef _BOOT_MODE
partition_module_info *modules[] = {
&sSunPartitionModule,
NULL
};
#endif