__ahci_hba_isr(const isr_param* param)
{
// ignore spurious interrupt
- if (!hba.ports[HBA_RIS])
+ if (!hba.base[HBA_RIS])
return;
u32_t port_num = 31 - __builtin_clz(hba.base[HBA_RIS]);
--- /dev/null
+/**
+ * @file blkpart_gpt.h
+ * @author Lunaixsky (lunaxisky@qq.com)
+ * @brief The GUID Partition Table (GPT)
+ * @version 0.1
+ * @date 2022-11-09
+ *
+ * @copyright Copyright (c) 2022
+ *
+ */
+#ifndef __LUNAIX_BLKPART_GPT_H
+#define __LUNAIX_BLKPART_GPT_H
+
+#include <lunaix/device.h>
+#include <lunaix/types.h>
+
+struct gpt_header
+{
+ u8_t signature[8];
+ u32_t rev;
+ u32_t hdr_size;
+ u32_t hdr_cksum;
+ u32_t reserved1;
+ u64_t hdr_lba;
+ u64_t hdr_backup_lba;
+ u64_t lba_start;
+ u64_t lba_end;
+ u8_t guid[16];
+ u64_t ents_lba;
+ u32_t ents_len;
+ u32_t ent_size;
+ u32_t ent_cksum;
+ // reserved start here
+} PACKED;
+
+struct gpt_entry
+{
+ u8_t pguid[16];
+ u8_t uguid[16];
+ u64_t start_lba;
+ u64_t end_lba;
+ u64_t attr_flags;
+ char name[72];
+} PACKED;
+
+int
+blkpart_probegpt(struct device* master);
+
+#endif /* __LUNAIX_BLKPART_GPT_H */
struct block_dev
{
- char bdev_id[DEV_ID_SIZE];
- char name[PARTITION_NAME_SIZE];
+ struct llist_header parts;
struct blkio_context* blkio;
struct device* dev;
+ char bdev_id[DEV_ID_SIZE];
+ char name[PARTITION_NAME_SIZE];
void* driver;
+ u64_t start_lba;
u64_t end_lba;
u32_t blk_size;
};
-struct lpt_entry
-{
- char part_name[PARTITION_NAME_SIZE];
- u64_t base_lba;
- u64_t end_lba;
-} __attribute__((packed));
-
// Lunaix Partition Table
struct lpt_header
{
void
blk_set_blkmapping(struct block_dev* bdev, void* fsnode);
+struct block_dev*
+blk_mount_part(struct block_dev* bdev,
+ const char* name,
+ size_t index,
+ u64_t start_lba,
+ u64_t end_lba);
+
#endif /* __LUNAIX_BLOCK_H */
blk_root = twifs_dir_node(NULL, "block");
}
-void
-__blk_rd_size(struct twimap* map)
-{
- struct block_dev* bdev = twimap_data(map, struct block_dev*);
- size_t secsize = bdev->blk_size;
- twimap_printf(map, "%u", bdev->end_lba * secsize);
-}
-
void
__blk_rd_lblksz(struct twimap* map)
{
}
void
-blk_set_blkmapping(struct block_dev* bdev, void* fsnode)
+__blk_rd_start_lba(struct twimap* map)
+{
+ struct block_dev* bdev = twimap_data(map, struct block_dev*);
+ twimap_printf(map, "%d", bdev->start_lba);
+}
+
+void
+__blk_rd_end_lba(struct twimap* map)
+{
+ struct block_dev* bdev = twimap_data(map, struct block_dev*);
+ twimap_printf(map, "%d", bdev->end_lba);
+}
+
+void
+__blk_rd_size(struct twimap* map)
+{
+ struct block_dev* bdev = twimap_data(map, struct block_dev*);
+ twimap_printf(
+ map, "%u", (u32_t)(bdev->end_lba - bdev->start_lba) * bdev->blk_size);
+}
+
+void
+__map_internal(struct block_dev* bdev, void* fsnode)
{
struct twifs_node* dev_root = (struct twifs_node*)fsnode;
map = twifs_mapping(dev_root, bdev, "name");
map->read = __blk_rd_name;
+
+ map = twifs_mapping(dev_root, bdev, "begin");
+ map->read = __blk_rd_start_lba;
+
+ map = twifs_mapping(dev_root, bdev, "end");
+ map->read = __blk_rd_end_lba;
+}
+
+void
+blk_set_blkmapping(struct block_dev* bdev, void* fsnode)
+{
+ struct twifs_node* dev_root = (struct twifs_node*)fsnode;
+
+ __map_internal(bdev, dev_root);
+
+ struct block_dev *pos, *n;
+ llist_for_each(pos, n, &bdev->parts, parts)
+ {
+ struct twifs_node* part_node = twifs_dir_node(dev_root, pos->bdev_id);
+ __map_internal(pos, part_node);
+ }
}
\ No newline at end of file
req->completed(req);
}
+ // FIXME Not working in first process! Need a dummy process.
// Wake all blocked processes on completion,
// albeit should be no more than one process in everycase (by design)
pwake_all(&req->wait);
--- /dev/null
+#include <klibc/string.h>
+#include <lunaix/blkpart_gpt.h>
+#include <lunaix/block.h>
+#include <lunaix/mm/valloc.h>
+#include <lunaix/status.h>
+
+#include <lib/crc.h>
+
+#define GPT_BLKSIZE 512
+#define LBA2OFF(lba) (lba * GPT_BLKSIZE)
+#define ENT_PER_BLK (GPT_BLKSIZE / sizeof(struct gpt_entry))
+
+#define GPTSIG_LO 0x20494645UL
+#define GPTSIG_HI 0x54524150UL
+
+static u8_t NULL_GUID[16] = { 0 };
+
+int
+blkpart_parse(struct device* master, struct gpt_header* header)
+{
+ struct block_dev* bdev = (struct block_dev*)master->underlay;
+ if (!bdev)
+ return ENODEV;
+
+ int errno;
+ u32_t ent_lba = (u32_t)header->ents_lba;
+ struct gpt_entry* ents_parial = (struct gpt_entry*)valloc(GPT_BLKSIZE);
+
+ for (size_t i = 0; i < header->ents_len; i++) {
+ if (!(i % ENT_PER_BLK)) {
+ errno = master->read(
+ master, ents_parial, LBA2OFF(ent_lba++), GPT_BLKSIZE);
+ if (errno < 0) {
+ goto done;
+ }
+ }
+
+ struct gpt_entry* ent = &ents_parial[i % ENT_PER_BLK];
+
+ // assuming the entries are not scattered around
+ if (!memcmp(ent->pguid, NULL_GUID, 16)) {
+ break;
+ }
+
+ // Convert UEFI's 512B LB representation into local LBA range.
+ u64_t slba_local = (ent->start_lba * GPT_BLKSIZE) / bdev->blk_size;
+ u64_t elba_local = (ent->end_lba * GPT_BLKSIZE) / (u64_t)bdev->blk_size;
+
+ // we ignore the partition name, as it rarely used.
+ blk_mount_part(bdev, NULL, i, slba_local, elba_local);
+ }
+
+done:
+ vfree(ents_parial);
+ return errno;
+}
+
+int
+blkpart_probegpt(struct device* master)
+{
+ int errno;
+ struct gpt_header* gpt_hdr = (struct gpt_header*)valloc(GPT_BLKSIZE);
+
+ if ((errno = master->read(master, gpt_hdr, LBA2OFF(1), LBA2OFF(1))) < 0) {
+ goto done;
+ }
+
+ if (*(u32_t*)&gpt_hdr->signature != GPTSIG_LO ||
+ *(u32_t*)&gpt_hdr->signature[4] != GPTSIG_HI) {
+ return 0;
+ }
+
+ u32_t crc = gpt_hdr->hdr_cksum;
+ gpt_hdr->hdr_cksum = 0;
+ if (crc32b((void*)gpt_hdr, sizeof(*gpt_hdr)) != crc) {
+ // FUTURE check the backup header
+ return EINVAL;
+ }
+
+ errno = blkpart_parse(master, gpt_hdr);
+done:
+ vfree(gpt_hdr);
+ return errno;
+}
\ No newline at end of file
#include <lunaix/mm/valloc.h>
#include <lunaix/syslog.h>
+#include <lunaix/blkpart_gpt.h>
+
#include <lunaix/spike.h>
#define BLOCK_EREAD 1
{
int errno;
struct block_dev* bdev = (struct block_dev*)dev->underlay;
- size_t bsize = bdev->blk_size, rd_block = offset / bsize,
+ size_t bsize = bdev->blk_size, rd_block = offset / bsize + bdev->start_lba,
r = offset % bsize, rd_size = 0;
if (!(len = MIN(len, ((size_t)bdev->end_lba - rd_block + 1) * bsize))) {
if (r) {
tmp_buf = vzalloc(bsize);
rd_size = MIN(len, bsize - r);
- vbuf->buf.size = rd_size;
+ vbuf->buf.size = bsize;
vbuf->buf.buffer = tmp_buf;
- vbuf_alloc(vbuf, buf + rd_size, len - rd_size);
+ if ((len - rd_size)) {
+ vbuf_alloc(vbuf, buf + rd_size, len - rd_size);
+ }
}
req = blkio_vrd(vbuf, rd_block, NULL, NULL, 0);
pwait(&req->wait);
+ // XXX temporary work-around
+ // in case pwait used in proc0. Need a dummy process!
+ wait_if((req->flags & BLKIO_PENDING));
+
if (!(errno = req->errcode)) {
memcpy(buf, tmp_buf + r, rd_size);
errno = len;
__block_write(struct device* dev, void* buf, size_t offset, size_t len)
{
struct block_dev* bdev = (struct block_dev*)dev->underlay;
- size_t bsize = bdev->blk_size, rd_block = offset / bsize,
+ size_t bsize = bdev->blk_size, rd_block = offset / bsize + bdev->start_lba,
r = offset % bsize;
if (!(len = MIN(len, ((size_t)bdev->end_lba - rd_block + 1) * bsize))) {
pwait(&req->wait);
+ // XXX temporary work-around
+ // in case pwait used in proc0. Need a dummy process!
+ wait_if((req->flags & BLKIO_PENDING));
+
int errno = req->errcode;
if (!errno) {
errno = len;
{
struct block_dev* bdev = cake_grab(lbd_pile);
memset(bdev, 0, sizeof(struct block_dev));
-
+ llist_init_head(&bdev->parts);
strncpy(bdev->name, blk_id, PARTITION_NAME_SIZE);
bdev->blkio = blkio_newctx(ioreq_handler);
goto error;
}
+ errno = blkpart_probegpt(bdev->dev);
+ if (errno < 0) {
+ kprintf(KERROR "Corrupted partition table. (%d)", errno);
+ } else if (!errno) {
+ // TODO try other PT parser...
+ }
+
struct twifs_node* dev_root = twifs_dir_node(blk_sysroot, bdev->bdev_id);
blk_set_blkmapping(bdev, dev_root);
fs_export(bdev, dev_root);
strcpy(bdev->bdev_id, dev->name_val);
dev_registry[free_slot++] = bdev;
return 1;
+}
+
+struct block_dev*
+blk_mount_part(struct block_dev* bdev,
+ const char* name,
+ size_t index,
+ u64_t start_lba,
+ u64_t end_lba)
+{
+ struct block_dev* pbdev = cake_grab(lbd_pile);
+ memcpy(pbdev, bdev, sizeof(*bdev));
+
+ struct device* dev =
+ device_addvol(NULL, pbdev, "%sp%d", bdev->bdev_id, index + 1);
+ dev->write = __block_write;
+ dev->read = __block_read;
+
+ pbdev->start_lba = start_lba;
+ pbdev->end_lba = end_lba;
+ pbdev->dev = dev;
+
+ strcpy(pbdev->bdev_id, dev->name_val);
+ if (name) {
+ strncpy(pbdev->name, name, PARTITION_NAME_SIZE);
+ }
+
+ llist_append(&bdev->parts, &pbdev->parts);
+
+ return pbdev;
}
\ No newline at end of file