1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
#include <cstdint>
#include <drivers/disk.hpp>
#include <generic/hhdm.hpp>
#include <generic/pmm.hpp>
#include <drivers/mbr.hpp>
#include <utils/assert.hpp>
#include <klibc/string.hpp>
#include <drivers/gpt.hpp>
#include <drivers/ext2.hpp>
const char* disk_type_to_str(partition_style disk_type) {
switch(disk_type) {
case partition_style::err:
return "Unknown";
case partition_style::mbr:
return "MBR";
case partition_style::gpt:
return "GPT";
case partition_style::raw:
return "Raw";
}
}
partition_style determine_disk_type(disk* target_disk) {
char* buffer = (char*)(pmm::freelist::alloc_4k() + etc::hhdm());
target_disk->read(target_disk->arg, (char*)buffer, 1, 1);
if(!klibc::memcmp((const char*)buffer, GPT_SIGNATURE, sizeof(GPT_SIGNATURE))) {
pmm::freelist::free((std::uint64_t)buffer - etc::hhdm());
return partition_style::gpt;
}
target_disk->read(target_disk->arg, (char*)buffer, 0, 1);
if(((mbr_sector*)buffer)->signature == 0xAA55) {
pmm::freelist::free((std::uint64_t)buffer - etc::hhdm());
return partition_style::mbr;
}
assert(0, "Unknown partition style");
return partition_style::err;
}
bool disk_selftest(disk* target_disk) {
char* buffer = (char*)(pmm::freelist::alloc_4k() + etc::hhdm());
if(target_disk->read(target_disk->arg, buffer, 0, 1) == true) {
pmm::freelist::free((std::uint64_t)buffer - etc::hhdm());
return true;
} else {
klibc::printf("Disk: Failed to do disk selftest\r\n");
return false;
}
}
const char* mbr_to_str(std::uint8_t type) {
switch (type)
{
case 0x83:
return "linux";
case 0xb:
return "fat32";
default:
return "unknown";
}
return "unknown";
}
void disk_do_mbr_linux(disk* new_disk, std::uint64_t start_lba) {
bytes_to_block_res b = bytes_to_blocks(1024, 1024, new_disk->lba_size);
char* buffer = (char*)(pmm::freelist::alloc_4k() + etc::hhdm());
new_disk->read(new_disk->arg, buffer, start_lba + b.lba, b.size_in_blocks);
ext2_superblock *sb = (ext2_superblock*)buffer;
if (sb->s_magic == EXT2_MAGIC) {
#ifdef MBR_ORANGE_TRACE
klibc::printf("Disk: Detected ext2\r\n");
#endif
drivers::ext2::init(new_disk, start_lba);
}
pmm::freelist::free((std::uint64_t)buffer - etc::hhdm());
}
void disk_do_mbr(disk* new_disk) {
char* buffer = (char*)(pmm::freelist::alloc_4k() + etc::hhdm());
new_disk->read(new_disk->arg, (char*)buffer, 0, 1);
mbr_sector* mbr = (mbr_sector*)buffer;
for(int i = 0; i < 4; i++) {
if(mbr->partitions[i].partition_type != 0) {
#ifdef MBR_ORANGE_TRACE
klibc::printf("Disk: Detected mbr partition type %s (%d), lba_start %lli\r\n", mbr_to_str(mbr->partitions[i].partition_type), mbr->partitions[i].partition_type, mbr->partitions[i].lba_start);
#endif
if(mbr->partitions[i].partition_type == 0x83) {
disk_do_mbr_linux(new_disk, mbr->partitions[i].lba_start);
}
}
}
pmm::freelist::free((std::uint64_t)buffer - etc::hhdm());
}
void drivers::init_disk(disk* new_disk) {
if(disk_selftest(new_disk) == false)
return;
partition_style style = determine_disk_type(new_disk);
klibc::printf("Disk: Detected %s partition style\r\n", disk_type_to_str(style));
switch (style)
{
case partition_style::mbr:
disk_do_mbr(new_disk);
break;
default:
assert(0,"unsupported disk\r\n");
break;
}
}
|