148 lines
3.7 KiB
C
148 lines
3.7 KiB
C
/**
|
|
* @file modules/dospart.c
|
|
* @brief DOS MBR partition table mapper
|
|
* @package x86_64
|
|
*
|
|
* Provides partition entries for disks.
|
|
*
|
|
* @copyright
|
|
* This file is part of ToaruOS and is released under the terms
|
|
* of the NCSA / University of Illinois License - see LICENSE.md
|
|
* Copyright (C) 2014-2021 K. Lange
|
|
*/
|
|
#include <kernel/types.h>
|
|
#include <kernel/module.h>
|
|
#include <kernel/vfs.h>
|
|
#include <kernel/printf.h>
|
|
#include <kernel/tokenize.h>
|
|
|
|
#define SECTORSIZE 512
|
|
|
|
typedef struct {
|
|
uint8_t status;
|
|
uint8_t chs_first_sector[3];
|
|
uint8_t type;
|
|
uint8_t chs_last_sector[3];
|
|
uint32_t lba_first_sector;
|
|
uint32_t sector_count;
|
|
} partition_t;
|
|
|
|
typedef struct {
|
|
uint8_t boostrap[446];
|
|
partition_t partitions[4];
|
|
uint8_t signature[2];
|
|
} __attribute__((packed)) mbr_t;
|
|
|
|
struct dos_partition_entry {
|
|
fs_node_t * device;
|
|
partition_t partition;
|
|
};
|
|
|
|
static ssize_t read_part(fs_node_t *node, off_t offset, size_t size, uint8_t *buffer) {
|
|
struct dos_partition_entry * device = (struct dos_partition_entry *)node->device;
|
|
|
|
if ((size_t)offset > device->partition.sector_count * SECTORSIZE) {
|
|
return 0;
|
|
}
|
|
|
|
if (offset + size > device->partition.sector_count * SECTORSIZE) {
|
|
size = device->partition.sector_count * SECTORSIZE - offset;
|
|
}
|
|
|
|
return read_fs(device->device, offset + device->partition.lba_first_sector * SECTORSIZE, size, buffer);
|
|
}
|
|
|
|
static ssize_t write_part(fs_node_t *node, off_t offset, size_t size, uint8_t *buffer) {
|
|
struct dos_partition_entry * device = (struct dos_partition_entry *)node->device;
|
|
|
|
if ((size_t)offset > device->partition.sector_count * SECTORSIZE) {
|
|
return 0;
|
|
}
|
|
|
|
if (offset + size > device->partition.sector_count * SECTORSIZE) {
|
|
size = device->partition.sector_count * SECTORSIZE - offset;
|
|
}
|
|
|
|
return write_fs(device->device, offset + device->partition.lba_first_sector * SECTORSIZE, size, buffer);
|
|
}
|
|
|
|
static void open_part(fs_node_t * node, unsigned int flags) {
|
|
return;
|
|
}
|
|
|
|
static void close_part(fs_node_t * node) {
|
|
return;
|
|
}
|
|
|
|
static fs_node_t * dospart_device_create(int i, fs_node_t * dev, mbr_t * mbr, int id) {
|
|
|
|
vfs_lock(dev);
|
|
|
|
struct dos_partition_entry * device = malloc(sizeof(struct dos_partition_entry));
|
|
memcpy(&device->partition, &mbr->partitions[id], sizeof(partition_t));
|
|
device->device = dev;
|
|
|
|
fs_node_t * fnode = malloc(sizeof(fs_node_t));
|
|
memset(fnode, 0x00, sizeof(fs_node_t));
|
|
fnode->inode = 0;
|
|
snprintf(fnode->name, 20, "dospart%d", i);
|
|
fnode->device = device;
|
|
fnode->uid = 0;
|
|
fnode->gid = 0;
|
|
fnode->mask = 0660;
|
|
fnode->length = device->partition.sector_count * SECTORSIZE; /* TODO */
|
|
fnode->flags = FS_BLOCKDEVICE;
|
|
fnode->read = read_part;
|
|
fnode->write = write_part;
|
|
fnode->open = open_part;
|
|
fnode->close = close_part;
|
|
fnode->readdir = NULL;
|
|
fnode->finddir = NULL;
|
|
fnode->ioctl = NULL; /* TODO, identify, etc? */
|
|
return fnode;
|
|
}
|
|
|
|
static fs_node_t * dospart_map(const char * device, const char * mount_path) {
|
|
char * arg = strdup(device);
|
|
char * argv[10];
|
|
tokenize(arg, ",", argv);
|
|
|
|
fs_node_t * dev = kopen(argv[0], 0);
|
|
if (!dev) {
|
|
return NULL;
|
|
}
|
|
|
|
mbr_t mbr;
|
|
read_fs(dev, 0, SECTORSIZE, (uint8_t *)&mbr);
|
|
|
|
if (mbr.signature[0] == 0x55 && mbr.signature[1] == 0xAA) {
|
|
for (int i = 0; i < 4; ++i) {
|
|
if (mbr.partitions[i].status & 0x80) {
|
|
fs_node_t * node = dospart_device_create(i, dev, &mbr, i);
|
|
char tmp[64];
|
|
snprintf(tmp, 20, "%s%d", device, i);
|
|
vfs_mount(tmp, node);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* VFS_MOUNT_PARTITION_MAPPER_SUCCESS? */
|
|
return (fs_node_t*)1;
|
|
}
|
|
|
|
static int dospart_initialize(int argc, char * argv[]) {
|
|
vfs_register("mbr", dospart_map);
|
|
return 0;
|
|
}
|
|
|
|
static int dospart_finalize(void) {
|
|
return 0;
|
|
}
|
|
|
|
struct Module metadata = {
|
|
.name = "dospart",
|
|
.init = dospart_initialize,
|
|
.fini = dospart_finalize,
|
|
};
|
|
|