Browse Source

GPT partitions

master
Mathieu Serandour 1 year ago
parent
commit
a4a3eb4191
  1. 38
      kernel/drivers/nvme/nvme.c
  2. 1
      kernel/drivers/nvme/nvme.h
  3. 25
      kernel/drivers/storage_interface.h
  4. 105
      kernel/fs/gpt.c
  5. 34
      kernel/fs/gpt.h
  6. 20
      kernel/lib/utf16le.c
  7. 18
      kernel/lib/utf16le.h

38
kernel/drivers/nvme/nvme.c

@ -29,6 +29,8 @@
#include "../../memory/vmap.h"
#include "../../int/irq.h"
#include "../../fs/gpt.h"
// for apic_eoi()
#include "../../int/apic.h"
@ -69,8 +71,12 @@ struct data {
// namespace ids array
struct namespace namespaces[HANDLED_NAMESPACES];
struct storage_interface si;
};
static
void perform_read_command(
struct data* data,
@ -718,21 +724,22 @@ int nvme_install(driver_t* this) {
this->status = DRIVER_STATE_OK;
void* buff = malloc(0x2000);
nvme_sync_read(
this,
0x1fca00 >> 9,
buff,
16
);
dump(
buff,
8192,
32,
DUMP_HEX8
);
if(data->nns >= 1) {
// if a usable namespace is detected,
// scan its partition table
// and mount its partitions
// fill the storage interface structure
data->si = (struct storage_interface) {
.capacity = data->namespaces[0].capacity,
.driver = this,
.lbashift = data->namespaces[0].block_size_shift,
.read = nvme_sync_read,
.write = nvme_sync_write,
};
gpt_scan(&data->si);
}
// installed
@ -910,6 +917,7 @@ void perform_write_command(
void* _buf,
size_t count
) {
panic("too dangerous operation");
// general assert protection
assert(lba < data->namespaces[0].capacity);
assert(lba + count < data->namespaces[0].capacity);

1
kernel/drivers/nvme/nvme.h

@ -3,7 +3,6 @@
#include <stdint.h>
#include <stddef.h>
struct driver;
int nvme_install(struct driver*);

25
kernel/drivers/storage_interface.h

@ -0,0 +1,25 @@
#pragma once
#include <stdint.h>
#include <stddef.h>
struct driver;
struct storage_interface {
struct driver* driver;
void (*read)(struct driver *,
uint64_t lba,
void* buf,
size_t count);
void (*write)(struct driver *,
uint64_t lba,
void* buf,
size_t count);
unsigned capacity;
unsigned lbashift;
};

105
kernel/fs/gpt.c

@ -0,0 +1,105 @@
#include "../lib/string.h"
#include "../lib/logging.h"
#include "../lib/utf16le.h"
#include "../lib/dump.h"
#include "../drivers/driver.h"
#include "../drivers/dev.h"
#include "gpt.h"
struct gpt_partition_descriptor {
GUID type_guid;
GUID partition_guid;
uint64_t begin;
uint64_t end;
uint64_t attributes;
wchar_t name[];
} __attribute__((packed));
static partition_t* partitions = NULL;
static unsigned n_partitions = 0;
static void register_partition(partition_t p) {
unsigned last = n_partitions++;
partitions = realloc(partitions, n_partitions * sizeof(partition_t));
partitions[last] = p;
}
void gpt_scan(const struct storage_interface* sti) {
void* buffer = malloc(1 << sti->lbashift);
// LBA 1: Partition Table Header
sti->read(sti->driver, 1, buffer, 1);
// magic
if(strcmp(buffer+0, "EFI PART")) {
log_warn("no GPT table found in device %s.",
sti->driver->device->name.ptr);
return;
}
// usually equal to 2
uint64_t partition_entry_array_lba = *(uint64_t*)(buffer+0x48);
unsigned n_partitions = *(uint32_t*)(buffer+0x50);
unsigned partition_entry_size = *(uint32_t*)(buffer+0x54);
log_warn(
"n_partitions=%lx, partition_entry_array_lba=%lx, "
"partition_entry_size=%x",
n_partitions,
partition_entry_array_lba,
partition_entry_size
);
unsigned size = (partition_entry_size * n_partitions);
buffer = realloc(buffer, size);
// LBA 1: Partition Entries
sti->read(sti->driver, partition_entry_array_lba,
buffer, size >> sti->lbashift);
// temporary pointer of gpt partition entry
void* ptr = buffer;
for(unsigned i = 0; i < n_partitions;
i++, ptr += partition_entry_size) {
struct gpt_partition_descriptor* entry = ptr;
if(entry->type_guid.low == 0 &&
entry->type_guid.high == 0)
continue;
char* name[36];
utf16le2ascii(name, entry->name, 35);
log_info(
"GPT Partition %s\n"
"LBA begin: %lx\n"
"LBA end: %lx\n"
"attributes: %lx\n",
name,
entry->begin,
entry->end,
entry->attributes
);
}
}

34
kernel/fs/gpt.h

@ -0,0 +1,34 @@
#pragma once
#include "../drivers/storage_interface.h"
typedef struct {
uint64_t low, high;
} GUID;
typedef struct partition {
const struct storage_interface* interface;
uint32_t type;
GUID partition_guid;
uint64_t begin;
uint64_t end;
uint64_t attributes;
// null terminated
char name[36];
} partition_t;
#define PARTITION_TYPE_
void gpt_scan(const struct storage_interface* sti);
// release partition information memory
void gpt_cleanup(void);

20
kernel/lib/utf16le.c

@ -0,0 +1,20 @@
#include "utf16le.h"
void utf16le2ascii(
char* __restrict__ ascii,
const uint16_t* __restrict__ utf16le,
size_t len
) {
char c;
for(;len>0;--len) {
*ascii++ = c = (*utf16le++) & 0xff;
if(!c) {
*ascii = '\0';
break;
}
}
}

18
kernel/lib/utf16le.h

@ -0,0 +1,18 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
/**
* @brief convert a utf16le encoded
* null-terminated string into a ascii string
*
* @param ascii destination pointer
* @param utf16le source pointer
* @param len maximum length to convert
*/
void utf16le2ascii(
char* __restrict__ ascii,
const uint16_t* __restrict__ utf16le,
size_t len);
Loading…
Cancel
Save