Skip to content

Commit 0a4980b

Browse files
committed
Added buffers to the best of my ability & improvements
1 parent a24c6de commit 0a4980b

12 files changed

Lines changed: 194 additions & 76 deletions

File tree

include/drivers/dt/dt.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#ifndef DT_H
22
#define DT_H
33

4+
#include <stdbigos/buffer.h>
45
#include <stdbigos/types.h>
56

67
struct dt_node;
@@ -9,7 +10,7 @@ struct dt_prop;
910
// Initializes the device tree driver
1011
// TODO: Currently parses the entire FDT at init, maybe change to lazy parsing later
1112
// Builds the actual tree structure handleable by the driver, 0 if success, <0 if error
12-
int dt_init(const void* fdt_blob, u32 blob_size);
13+
int dt_init(buffer_t fdt_buf);
1314

1415
// Frees all memory used by the arena
1516
void dt_cleanup(void);

include/stdbigos/bitutils.h

Lines changed: 3 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,37 +3,10 @@
33

44
#include <stdbigos/types.h>
55

6-
// Reads a single 32-bit unsigned integer value from the specified address
7-
static inline u32 read_be32(const void* addr) {
8-
const u8* bytes = (const u8*)addr;
9-
return ((u32)bytes[0] << 24) | ((u32)bytes[1] << 16) | ((u32)bytes[2] << 8) | ((u32)bytes[3] << 0);
10-
};
6+
u32 read_be32(const void* addr);
117

12-
// Reads a single 64-bit unsigned integer value from the specified address
13-
static inline u64 read_be64(const void* addr) {
14-
const u8* bytes = (const u8*)addr;
15-
return ((u64)bytes[0] << 56) | ((u64)bytes[1] << 48) | ((u64)bytes[2] << 40) | ((u64)bytes[3] << 32) |
16-
((u64)bytes[4] << 24) | ((u64)bytes[5] << 16) | ((u64)bytes[6] << 8) | ((u64)bytes[7] << 0);
17-
};
8+
u64 read_be64(const void* addr);
189

19-
// Helper for aligning to 4 bytes
20-
static inline u32 align4(u32 off) {
21-
return (off + 3) & ~3u;
22-
}
23-
24-
// Helper for aligning to 8 bytes
25-
static inline u32 align8(u32 off) {
26-
return (off + 7) & ~7u;
27-
}
28-
29-
// Helper for aligning to 16 bytes
30-
static inline u32 align16(u32 off) {
31-
return (off + 15) & ~15u;
32-
}
33-
34-
// Helper for aligning to 32 bytes
35-
static inline u32 align32(u32 off) {
36-
return (off + 31) & ~31u;
37-
}
10+
u32 alignN(u32 num, u32 align);
3811

3912
#endif

include/stdbigos/buffer.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#ifndef DRIVERS_DT_BUFFER_H
2+
#define DRIVERS_DT_BUFFER_H
3+
4+
#include <stdbigos/types.h>
5+
6+
// Error codes
7+
#define BUFFER_OK 0
8+
#define BUFFER_OUT_OF_BOUNDS -1
9+
10+
typedef struct buffer_t {
11+
const void* data;
12+
size_t size;
13+
} buffer_t;
14+
15+
// Helper to create a buffer
16+
static inline buffer_t make_buffer(const void* data, size_t size) {
17+
buffer_t buf = {data, size};
18+
return buf;
19+
}
20+
21+
// Read big-endian 32-bit from buffer at given offset
22+
int buffer_read_u32_be(const buffer_t* buf, size_t offset, u32* out);
23+
24+
// Read big-endian 64-bit from buffer at given offset
25+
int buffer_read_u64_be(const buffer_t* buf, size_t offset, u64* out);
26+
27+
// Read little-endian 32-bit from buffer at given offset
28+
int buffer_read_u32_le(const buffer_t* buf, size_t offset, u32* out);
29+
30+
// Read little-endian 64-bit from buffer at given offset
31+
int buffer_read_u64_le(const buffer_t* buf, size_t offset, u64* out);
32+
33+
// Read a zero-terminated C-string from buf at offset
34+
int buffer_read_cstring(const buffer_t* buf, size_t offset, const char** out_str);
35+
36+
#endif

src/drivers/dt/dt_access.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,24 @@ static void sbi_puts(const char* str) {
1111
while (*str) sbi_debug_console_write_byte(*str++);
1212
}
1313

14+
static void sbi_put_u32(u32 num) {
15+
char buf[11];
16+
int i = 10;
17+
buf[i] = '\0';
18+
i--;
19+
if (num == 0) {
20+
sbi_puts("0");
21+
return;
22+
}
23+
24+
while (num && i >= 0) {
25+
buf[i] = (num % 10 + '0');
26+
i--;
27+
num /= 10;
28+
}
29+
sbi_puts(&buf[i + 1]);
30+
}
31+
1432
// There has to be a better way to do this
1533
static void gap(u8 size) {
1634
for (u8 i = 0; i < size; i++) sbi_puts("\t");

src/drivers/dt/dt_alloc.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "dt_alloc.h"
22

33
#include <stdbigos/bitutils.h>
4+
#include <stdbigos/buffer.h>
45
#include <stdbigos/types.h>
56

67
// Arena
@@ -32,7 +33,7 @@ void* dt_alloc(u32 size) {
3233
return nullptr;
3334

3435
// Align to 4 bytes
35-
u32 align = align4(size);
36+
u32 align = alignN(size, 4);
3637

3738
if (arena_offset + align > arena_size)
3839
return nullptr;

src/drivers/dt/dt_init.c

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#include <drivers/dt/dt.h>
2-
#include <stdbigos/bitutils.h>
2+
#include <stdbigos/buffer.h>
33
#include <stdbigos/types.h>
44

55
#include "dt_alloc.h"
@@ -19,30 +19,38 @@ struct dt_node* root_node = nullptr;
1919
#define FDT_OFF_SIZE_DT_STRINGS 0x20
2020
#define FDT_OFF_SIZE_DT_STRUCT 0x24
2121

22-
int dt_init(const void* fdt_blob, u32 blob_size) {
23-
if (!fdt_blob || blob_size < (FDT_OFF_OFF_DT_STRINGS + 4))
22+
int dt_init(buffer_t fdt_buf) {
23+
if (!fdt_buf.data || fdt_buf.size < (FDT_OFF_OFF_DT_STRINGS + 4))
2424
return -1;
2525

26-
const u8* fdt_u8 = (const u8*)fdt_blob;
27-
u32 magic = read_be32(fdt_u8 + FDT_OFF_MAGIC);
28-
if (magic != FDT_MAGIC)
26+
u32 magic;
27+
if (buffer_read_u32_be(&fdt_buf, 0, &magic) != BUFFER_OK || magic != FDT_MAGIC)
2928
return -2;
3029

31-
u32 total_size = read_be32(fdt_u8 + FDT_OFF_TOTAL_SIZE);
32-
u32 struct_off = read_be32(fdt_u8 + FDT_OFF_OFF_DT_STRUCT);
33-
u32 strings_off = read_be32(fdt_u8 + FDT_OFF_OFF_DT_STRINGS);
30+
u32 total_size;
31+
if (buffer_read_u32_be(&fdt_buf, FDT_OFF_TOTAL_SIZE, &total_size) != BUFFER_OK)
32+
return -2;
33+
34+
u32 struct_off;
35+
if (buffer_read_u32_be(&fdt_buf, FDT_OFF_OFF_DT_STRUCT, &struct_off) != BUFFER_OK)
36+
return -2;
3437

35-
u32 struct_size = read_be32(fdt_u8 + FDT_OFF_SIZE_DT_STRUCT);
38+
u32 strings_off;
39+
if (buffer_read_u32_be(&fdt_buf, FDT_OFF_OFF_DT_STRINGS, &strings_off) != BUFFER_OK)
40+
return -2;
3641

37-
if (total_size > blob_size || struct_off + struct_size > blob_size)
42+
u32 struct_size;
43+
if (buffer_read_u32_be(&fdt_buf, FDT_OFF_SIZE_DT_STRUCT, &struct_size) != BUFFER_OK)
44+
return -2;
45+
46+
if (struct_off + struct_size > total_size)
3847
return -3;
3948

4049
if (dt_arena_init(dt_arena_buffer, DT_ARENA_SIZE) < 0)
4150
return -4;
4251

4352
u32 offset = struct_off + 4;
44-
45-
root_node = parse_subtree(fdt_blob, &offset, struct_off + struct_size, strings_off, nullptr);
53+
root_node = parse_subtree(&fdt_buf, &offset, struct_off + struct_size, strings_off, nullptr);
4654
if (!root_node)
4755
return -5;
4856

src/drivers/dt/dt_node.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,20 @@
44
#include <stdbigos/types.h>
55

66
// Both prop and node structures are lists with outside pointers only to the first element
7-
struct dt_prop {
7+
typedef struct dt_prop {
88
const char* name;
99
const void* value;
1010
u32 data_length;
1111
struct dt_prop* next_prop;
12-
};
12+
} dt_prop;
1313

14-
struct dt_node {
14+
typedef struct dt_node {
1515
const char* name;
1616
u32 phandle;
1717
struct dt_prop* props;
1818
struct dt_node* parent;
1919
struct dt_node* first_child;
2020
struct dt_node* next_sibling;
21-
};
21+
} dt_node;
2222

2323
#endif

src/drivers/dt/dt_parser.c

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "dt_parser.h"
22

33
#include <stdbigos/bitutils.h>
4+
#include <stdbigos/buffer.h>
45
#include <stdbigos/string.h>
56
#include <stdbigos/types.h>
67

@@ -16,47 +17,50 @@
1617

1718
// Function to parse a block of properties starting at props_offset with props_size size in the FDT with fdt
1819
// being a ptr to the start of the flattened device tree blob
19-
struct dt_prop* parse_props(const void* fdt, u32 props_offset, u32 props_size, u32 str_offset) {
20+
struct dt_prop* parse_props(buffer_t* fdt_buf, u32 props_offset, u32 props_size, u32 str_offset) {
2021
u32 curr_offset = props_offset;
21-
const u8* fdt_u8 = (const u8*)fdt;
22+
2223
struct dt_prop* head = nullptr;
2324
struct dt_prop** pp = &head;
2425

2526
while (curr_offset < props_offset + props_size) {
26-
u32 tag = read_be32(fdt_u8 + curr_offset);
27+
u32 tag;
28+
buffer_read_u32_be(fdt_buf, curr_offset, &tag);
2729

2830
// Because of the separation of parsing properties and nodes, we don't want to parse non-properties
2931
if (tag != FDT_PROP)
3032
break;
3133

3234
curr_offset += 4;
33-
u32 len = read_be32(fdt_u8 + curr_offset);
35+
u32 len;
36+
buffer_read_u32_be(fdt_buf, curr_offset, &len);
3437
curr_offset += 4;
35-
u32 name_offset = read_be32(fdt_u8 + curr_offset);
38+
u32 name_offset;
39+
buffer_read_u32_be(fdt_buf, curr_offset, &name_offset);
3640
curr_offset += 4;
3741
struct dt_prop* new_prop = dt_alloc(sizeof(*new_prop));
3842
new_prop->data_length = len;
3943
new_prop->next_prop = nullptr;
4044

41-
new_prop->name = (const char*)(fdt_u8 + str_offset + name_offset);
45+
buffer_read_cstring(fdt_buf, str_offset + name_offset, &new_prop->name);
4246
// sbi_puts(new_prop->name);
4347
// sbi_puts("\n");
4448

45-
new_prop->value = fdt_u8 + curr_offset;
49+
// Forced
50+
new_prop->value = (const u8*)fdt_buf->data + curr_offset;
4651

4752
// At first it sets the head in the right place, then it sets the next_prop of the previous property to point to
4853
// the current property
4954
*pp = new_prop;
5055
pp = &new_prop->next_prop;
5156

52-
curr_offset = align4(curr_offset + len);
57+
curr_offset = alignN(curr_offset + len, 4);
5358
}
5459
return head;
5560
}
5661

5762
// Function to recursively parse a subtree at the given offset
58-
struct dt_node* parse_subtree(const void* fdt, u32* offset, u32 max_offset, u32 str_offset, struct dt_node* parent) {
59-
const u8* fdt_u8 = (const u8*)fdt;
63+
struct dt_node* parse_subtree(buffer_t* fdt_buf, u32* offset, u32 max_offset, u32 str_offset, struct dt_node* parent) {
6064
struct dt_node* node = dt_alloc(sizeof(*node));
6165

6266
if (!node)
@@ -70,44 +74,50 @@ struct dt_node* parse_subtree(const void* fdt, u32* offset, u32 max_offset, u32
7074

7175
u32 curr_offset = *offset;
7276

73-
if (read_be32(fdt_u8 + curr_offset - 4) != FDT_BEGIN_NODE) {
74-
return nullptr;
75-
}
77+
u32 tag;
7678

77-
const char* name = (const char*)(fdt_u8 + curr_offset);
79+
if (buffer_read_u32_be(fdt_buf, curr_offset - 4, &tag) != BUFFER_OK || tag != FDT_BEGIN_NODE)
80+
return nullptr;
7881

79-
if (!name)
82+
const char* name;
83+
if (buffer_read_cstring(fdt_buf, curr_offset, &name) != BUFFER_OK)
8084
return nullptr;
8185

86+
// After this point all reads from the buffer should be correct
87+
8288
u32 name_len = strlen(name) + 1;
8389

8490
node->name = name;
8591

86-
curr_offset = align4(curr_offset + name_len);
92+
curr_offset = alignN(curr_offset + name_len, 4);
8793

8894
u32 props_off = curr_offset;
8995
while (curr_offset < max_offset) {
90-
u32 tag = read_be32(fdt_u8 + curr_offset);
96+
u32 tag;
97+
buffer_read_u32_be(fdt_buf, curr_offset, &tag);
9198
if (tag != FDT_PROP)
9299
break;
93-
u32 p_len = read_be32(fdt_u8 + curr_offset + 4);
100+
101+
u32 p_len;
102+
buffer_read_u32_be(fdt_buf, curr_offset + 4, &p_len);
94103

95104
curr_offset += 12; // Skip tag, length, name_offset
96-
curr_offset = align4(curr_offset + p_len);
105+
curr_offset = alignN(curr_offset + p_len, 4);
97106
}
98-
99107
u32 props_len = curr_offset - props_off;
100108

101-
node->props = parse_props(fdt, props_off, props_len, str_offset);
109+
node->props = parse_props(fdt_buf, props_off, props_len, str_offset);
102110

103-
curr_offset = align4(props_off + props_len);
111+
curr_offset = alignN(props_off + props_len, 4);
104112

105113
while (curr_offset < max_offset) {
106-
u32 tag = read_be32(fdt_u8 + curr_offset);
114+
u32 tag;
115+
buffer_read_u32_be(fdt_buf, curr_offset, &tag);
116+
107117
curr_offset += 4;
108118
switch (tag) {
109119
case FDT_BEGIN_NODE:
110-
struct dt_node* child = parse_subtree(fdt, &curr_offset, max_offset, str_offset, node);
120+
struct dt_node* child = parse_subtree(fdt_buf, &curr_offset, max_offset, str_offset, node);
111121

112122
if (child) {
113123
if (!node->first_child)

src/drivers/dt/dt_parser.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
#ifndef DT_PARSER_H
22
#define DT_PARSER_H
33

4+
#include <stdbigos/buffer.h>
45
#include <stdbigos/types.h>
56

6-
struct dt_prop* parse_props(const void* fdt, u32 props_offset, u32 props_size, u32 str_offset);
7+
struct dt_prop* parse_props(buffer_t* fdt_buf, u32 props_offset, u32 props_size, u32 str_offset);
78

8-
struct dt_node* parse_subtree(const void* fdt, u32* offset, u32 max_offset, u32 str_offset, struct dt_node* parent);
9+
struct dt_node* parse_subtree(buffer_t* fdt_buf, u32* offset, u32 max_offset, u32 str_offset, struct dt_node* parent);
910

1011
#endif

src/example_dtree/entry.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <drivers/dt/dt_props.h>
44
#include <drivers/uart.h>
55
#include <stdbigos/bitutils.h>
6+
#include <stdbigos/buffer.h>
67
#include <stdbigos/sbi.h>
78
#include <stdbigos/types.h>
89

@@ -48,8 +49,9 @@
4849

4950
void main([[maybe_unused]] u32 hartid, const void* fdt) {
5051
u32 blob_size = read_be32((const u8*)fdt + 4);
52+
buffer_t buf = make_buffer(fdt, blob_size);
5153

52-
if (dt_init(fdt, blob_size) < 0) {
54+
if (dt_init(buf) < 0) {
5355
sbi_puts("DT_INIT FAILED\n");
5456
return;
5557
}

0 commit comments

Comments
 (0)