feat: open(2), close(2), mkdir(2) and readdir(2) syscall
[lunaix-os.git] / lunaix-os / kernel / block.c
1 #include <hal/ahci/hba.h>
2 #include <klibc/string.h>
3 #include <lib/crc.h>
4 #include <lunaix/block.h>
5 #include <lunaix/mm/cake.h>
6 #include <lunaix/mm/valloc.h>
7 #include <lunaix/syslog.h>
8
9 #define BLOCK_EREAD 1
10 #define BLOCK_ESIG 2
11 #define BLOCK_ECRC 3
12 #define BLOCK_EFULL 3
13
14 LOG_MODULE("BLOCK")
15
16 #define MAX_DEV 32
17
18 struct cake_pile* lbd_pile;
19 struct block_dev** dev_registry;
20
21 int free_slot = 0;
22
23 int
24 __block_mount_partitions(struct hba_device* hd_dev);
25
26 int
27 __block_register(struct block_dev* dev);
28
29 void
30 block_init()
31 {
32     lbd_pile = cake_new_pile("block_dev", sizeof(struct block_dev), 1, 0);
33     dev_registry = vcalloc(sizeof(struct block_dev*), MAX_DEV);
34 }
35
36 int
37 block_mount_disk(struct hba_device* hd_dev)
38 {
39     int errno = 0;
40     struct block_dev* dev = cake_grab(lbd_pile);
41     strncpy(dev->name, hd_dev->model, PARTITION_NAME_SIZE);
42     dev->hd_dev = hd_dev;
43     dev->base_lba = 0;
44     dev->end_lba = hd_dev->max_lba;
45     if (!__block_register(dev)) {
46         errno = BLOCK_EFULL;
47         goto error;
48     }
49
50     if ((errno = __block_mount_partitions(hd_dev))) {
51         goto error;
52     }
53
54 error:
55     kprintf(KERROR "Fail to mount hd: %s[%s] (%x)",
56             hd_dev->model,
57             hd_dev->serial_num,
58             -errno);
59 }
60
61 int
62 __block_mount_partitions(struct hba_device* hd_dev)
63 {
64     int errno = 0;
65     void* buffer = valloc_dma(hd_dev->block_size);
66     if (!hd_dev->ops.read_buffer(hd_dev, 1, buffer, hd_dev->block_size)) {
67         errno = BLOCK_EREAD;
68         goto done;
69     }
70
71     struct lpt_header* header = (struct lpt_header*)buffer;
72     if (header->signature != LPT_SIG) {
73         errno = BLOCK_ESIG;
74         goto done;
75     }
76
77     if (header->crc != crc32b(buffer, sizeof(*header))) {
78         errno = BLOCK_ECRC;
79         goto done;
80     }
81
82     uint64_t lba = header->pt_start_lba;
83     int j = 0;
84     int count_per_sector = hd_dev->block_size / sizeof(struct lpt_entry);
85     while (lba < header->pt_end_lba) {
86         if (!hd_dev->ops.read_buffer(hd_dev, lba, buffer, hd_dev->block_size)) {
87             errno = BLOCK_EREAD;
88             goto done;
89         }
90         struct lpt_entry* entry = (struct lpt_entry*)buffer;
91         for (int i = 0; i < count_per_sector; i++, j++) {
92             struct block_dev* dev = cake_grab(lbd_pile);
93             strncpy(dev->name, entry->part_name, PARTITION_NAME_SIZE);
94             dev->hd_dev = hd_dev;
95             dev->base_lba = entry->base_lba;
96             dev->end_lba = entry->end_lba;
97             __block_register(dev);
98
99             if (j >= header->table_len) {
100                 goto done;
101             }
102         }
103     }
104
105 done:
106     vfree_dma(buffer);
107     return -errno;
108 }
109
110 int
111 __block_register(struct block_dev* dev)
112 {
113     if (free_slot >= MAX_DEV) {
114         return 0;
115     }
116
117     dev_registry[free_slot++] = dev;
118     return 1;
119 }