--- /dev/null
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * All rights reserved.
+ * See LICENSE for details.
+ *
+ * Source: https://github.com/tadryanom/AdrOS
+ */
+
+#ifndef PARTITION_H
+#define PARTITION_H
+
+#include "blockdev.h"
+#include <stddef.h>
+#include <stdint.h>
+
+/* Maximum number of partitions in the system */
+#define PARTITION_MAX 32
+
+/* Partition types (MBR) */
+#define PART_TYPE_EMPTY 0x00
+#define PART_TYPE_FAT12 0x01
+#define PART_TYPE_FAT16 0x04
+#define PART_TYPE_EXTENDED 0x05
+#define PART_TYPE_FAT16B 0x06
+#define PART_TYPE_NTFS 0x07
+#define PART_TYPE_FAT32 0x0B
+#define PART_TYPE_FAT32_LBA 0x0C
+#define PART_TYPE_EXTENDED_LBA 0x0F
+#define PART_TYPE_LINUX 0x83
+#define PART_TYPE_LINUX_SWAP 0x82
+
+typedef struct partition {
+ block_device_t* parent; /* Parent block device (hda, vda, etc.) */
+ uint32_t start_lba; /* Starting LBA of partition */
+ uint32_t sector_count; /* Number of sectors in partition */
+ uint8_t partition_type; /* Partition type (MBR/GPT) */
+ uint8_t partition_number; /* Partition number (1-4 for primary MBR) */
+ char name[32]; /* e.g. "hda1", "vda2" */
+ int refcount; /* Number of filesystems using this partition */
+} partition_t;
+
+/* Register a partition. Returns 0 on success, -ENOSPC if table full. */
+int partition_register(const partition_t* part);
+
+/* Look up a partition by name (e.g. "hda1"). Returns pointer or NULL. */
+partition_t* partition_find(const char* name);
+
+/* Look up a partition by parent device and partition number. */
+partition_t* partition_find_by_device(block_device_t* parent, uint8_t partition_number);
+
+/* Increment partition refcount (called when filesystem mounts). */
+void partition_claim(partition_t* part);
+
+/* Decrement partition refcount (called when filesystem unmounts). */
+void partition_release(partition_t* part);
+
+/* Initialize partition subsystem lock */
+void partition_init_lock(void);
+
+#endif /* PARTITION_H */
--- /dev/null
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * All rights reserved.
+ * See LICENSE for details.
+ *
+ * Source: https://github.com/tadryanom/AdrOS
+ */
+
+#include "partition.h"
+#include "blockdev.h"
+#include "spinlock.h"
+#include "console.h"
+#include "errno.h"
+
+#include <string.h>
+
+static partition_t g_partitions[PARTITION_MAX];
+static int g_partition_count = 0;
+static spinlock_t g_partition_lock;
+
+void partition_init_lock(void) {
+ spinlock_init(&g_partition_lock);
+}
+
+int partition_register(const partition_t* part) {
+ if (!part) return -EINVAL;
+ if (!part->parent) return -EINVAL;
+
+ uintptr_t flags = spin_lock_irqsave(&g_partition_lock);
+
+ if (g_partition_count >= PARTITION_MAX) {
+ spin_unlock_irqrestore(&g_partition_lock, flags);
+ return -ENOSPC;
+ }
+
+ /* Check for duplicate name */
+ for (int i = 0; i < g_partition_count; i++) {
+ if (strcmp(g_partitions[i].name, part->name) == 0) {
+ /* Update existing entry */
+ g_partitions[i] = *part;
+ spin_unlock_irqrestore(&g_partition_lock, flags);
+ return 0;
+ }
+ }
+
+ g_partitions[g_partition_count++] = *part;
+ spin_unlock_irqrestore(&g_partition_lock, flags);
+ return 0;
+}
+
+partition_t* partition_find(const char* name) {
+ if (!name) return NULL;
+
+ uintptr_t flags = spin_lock_irqsave(&g_partition_lock);
+ partition_t* result = NULL;
+ for (int i = 0; i < g_partition_count; i++) {
+ if (strcmp(g_partitions[i].name, name) == 0) {
+ result = &g_partitions[i];
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&g_partition_lock, flags);
+ return result;
+}
+
+partition_t* partition_find_by_device(block_device_t* parent, uint8_t partition_number) {
+ if (!parent) return NULL;
+
+ uintptr_t flags = spin_lock_irqsave(&g_partition_lock);
+ partition_t* result = NULL;
+ for (int i = 0; i < g_partition_count; i++) {
+ if (g_partitions[i].parent == parent &&
+ g_partitions[i].partition_number == partition_number) {
+ result = &g_partitions[i];
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&g_partition_lock, flags);
+ return result;
+}
+
+void partition_claim(partition_t* part) {
+ if (!part) return;
+ uintptr_t flags = spin_lock_irqsave(&g_partition_lock);
+ part->refcount++;
+ spin_unlock_irqrestore(&g_partition_lock, flags);
+}
+
+void partition_release(partition_t* part) {
+ if (!part) return;
+ uintptr_t flags = spin_lock_irqsave(&g_partition_lock);
+ if (part->refcount > 0)
+ part->refcount--;
+ spin_unlock_irqrestore(&g_partition_lock, flags);
+}