Skip to content

Commit 909031d

Browse files
authored
Implement basic DTB parser (#19)
1 parent 667ff58 commit 909031d

3 files changed

Lines changed: 38 additions & 43 deletions

File tree

.github/workflows/kernel-build.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ jobs:
2626
- name: Install CMake
2727
uses: lukka/get-cmake@latest
2828

29+
# TODO: On some platforms ARMV7 for example, we should test with different board Virtaul, RPI2B, etc.
2930
- name: Install QEMU
3031
run: |
3132
sudo apt-get update

src/Kernel/Platform.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ typedef struct
1212
ReadOnlySpanChar Name;
1313
uint32_t ArchitectureBits;
1414
uint8_t BootCpuId;
15+
// TODO: Add Board Name / Computer name / Platform form name
1516
} PlatformInformation;
1617

1718
// TODO: We should maybe put that in common and call it SystemDevice or SystemStaticDevice

src/Kernel/Platforms/RiscV/Platform.c

Lines changed: 36 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
uintptr_t globalBootHartId;
99
uintptr_t globalDeviceTreeData;
1010

11+
// TODO: Merge get devices into one function. But maybe GetInformation is not great
12+
// because we retrieve the whole device map also
1113
PlatformInformation PlatformGetInformation()
1214
{
1315
return (PlatformInformation)
@@ -22,12 +24,13 @@ PlatformInformation PlatformGetInformation()
2224
// TODO: We should have a create binary reader that take the encoding and the pointer
2325
// TODO: It would be cool if it could work with streams but it seems too much
2426
// TODO: This function should take into account the endianness of the platform
25-
uint32_t BinaryReadUint32Old(uintptr_t pointer)
27+
uint32_t ConvertBytesToUint32(ReadOnlySpanUint8 data, ByteOrder byteOrder)
2628
{
27-
// TODO: For now big endian -> little endian conversion
28-
auto result = *(uint32_t*)pointer;
29+
// TODO: Check length is at least 4
30+
// TODO: For now big endian -> little endian conversion
31+
auto result = *(uint32_t*)data.Pointer;
2932

30-
if (PLATFORM_BYTE_ORDER == ByteOrder_LittleEndian)
33+
if (PLATFORM_BYTE_ORDER != byteOrder)
3134
{
3235
result = __builtin_bswap32(result);
3336
}
@@ -55,18 +58,22 @@ BinaryReader CreateBinaryReader(ReadOnlySpanUint8 data, ByteOrder byteOrder)
5558
uint32_t BinaryReadUint32(BinaryReader* reader)
5659
{
5760
auto span = SpanSliceFrom(reader->Data, reader->CurrentOffset);
61+
reader->CurrentOffset += sizeof(uint32_t);
62+
63+
return ConvertBytesToUint32(span, reader->ByteOrder);
64+
}
65+
66+
// TODO: When we have memoryarena we can maybe do better
67+
void BinaryReadBytes(BinaryReader* reader, size_t length, SpanUint8* output)
68+
{
69+
auto span = SpanSlice(reader->Data, reader->CurrentOffset, length);
5870
// TODO: For now big endian -> little endian conversion
5971
// TODO: Do the other conversions
60-
auto result = *(uint32_t*)span.Pointer;
61-
62-
if (PLATFORM_BYTE_ORDER == ByteOrder_LittleEndian)
63-
{
64-
result = __builtin_bswap32(result);
65-
}
6672

67-
reader->CurrentOffset += sizeof(uint32_t);
73+
MemoryCopy(*output, span);
6874

69-
return result;
75+
output->Length = length;
76+
reader->CurrentOffset += length;
7077
}
7178

7279
// TODO: When we have memoryarena we can maybe do better
@@ -93,7 +100,7 @@ void BinarySetOffset(BinaryReader* reader, size_t offset)
93100
reader->CurrentOffset = offset;
94101
}
95102

96-
void DeviceTreeReadNode(BinaryReader* reader, size_t stringDataOffset)
103+
bool DeviceTreeReadNode(BinaryReader* reader, size_t stringDataOffset)
97104
{
98105
auto testNode = BinaryReadUint32(reader);
99106

@@ -114,12 +121,8 @@ void DeviceTreeReadNode(BinaryReader* reader, size_t stringDataOffset)
114121
auto length = BinaryReadUint32(reader);
115122
auto nameOffset = BinaryReadUint32(reader);
116123

117-
if (length != 4)
118-
{
119-
KernelConsolePrint(String(" Unknown length: %d\n"), length);
120-
}
121-
122-
auto value = BinaryReadUint32(reader);
124+
auto value = StackAllocUint8(1024);
125+
BinaryReadBytes(reader, length, &value);
123126

124127
auto offset = reader->CurrentOffset;
125128
BinarySetOffset(reader, stringDataOffset + nameOffset);
@@ -128,21 +131,26 @@ void DeviceTreeReadNode(BinaryReader* reader, size_t stringDataOffset)
128131
BinaryReadString(reader, &name);
129132

130133
BinarySetOffset(reader, MemoryAlignUp(offset, 4));
131-
KernelConsolePrint(String(" Property: %s, %d\n"), name, value);
134+
KernelConsolePrint(String(" Property: %s\n"), name);
132135
}
133-
else
136+
else if (testNode == 0x09)
134137
{
135-
KernelConsolePrint(String("Unknown Node: %d\n"), testNode);
138+
return false;
136139
}
140+
141+
return true;
137142
}
138143

139144
PlatformDevices PlatformGetDevices()
140145
{
141-
auto dtbMagic = BinaryReadUint32Old(globalDeviceTreeData);
142-
auto sizeInBytes = BinaryReadUint32Old(globalDeviceTreeData + sizeof(uint32_t));
146+
auto dtbHeaderData = CreateReadOnlySpanUint8((uint8_t*)globalDeviceTreeData, sizeof(uint32_t) * 2);
147+
148+
auto dtbMagic = ConvertBytesToUint32(dtbHeaderData, ByteOrder_BigEndian);
149+
auto sizeInBytes = ConvertBytesToUint32(SpanSliceFrom(dtbHeaderData, sizeof(uint32_t)), ByteOrder_BigEndian);
143150

151+
KernelConsolePrint(String("MagicDTB: %x\n"), dtbMagic);
144152
// TODO: Check magic
145-
// TODO: Check boot_cpuid_phys
153+
// TODO: Verify version
146154

147155
auto dataSpan = CreateReadOnlySpanUint8((const uint8_t*)globalDeviceTreeData, sizeInBytes);
148156
auto reader = CreateBinaryReader(dataSpan, ByteOrder_BigEndian);
@@ -155,24 +163,9 @@ PlatformDevices PlatformGetDevices()
155163

156164
BinarySetOffset(&reader, structureOffset);
157165

158-
DeviceTreeReadNode(&reader, stringDataOffset);
159-
DeviceTreeReadNode(&reader, stringDataOffset);
160-
DeviceTreeReadNode(&reader, stringDataOffset);
161-
162-
DeviceTreeReadNode(&reader, stringDataOffset);
163-
DeviceTreeReadNode(&reader, stringDataOffset);
164-
DeviceTreeReadNode(&reader, stringDataOffset);
165-
166-
167-
/* This is a property node parsing
168-
testNode = BinaryReadUint32(&reader);
169-
length = BinaryReadUint32(&reader);
170-
nameOffset = BinaryReadUint32(&reader);
171-
KernelConsolePrint(String("TestNode: %d, %d, %d\n"), testNode, length, nameOffset);
172-
auto test = SpanSliceFrom(dataSpan, stringDataOffset + nameOffset);
173-
KernelConsolePrint(String("Test: %s\n"), test);
174-
*/
175-
166+
while (DeviceTreeReadNode(&reader, stringDataOffset))
167+
{
168+
}
176169

177170
// TODO: We parse DTB here for now but it will be moved in Kernel/Devices/DTB
178171
return (PlatformDevices)

0 commit comments

Comments
 (0)