Completely print out FDT

This commit is contained in:
Furkan Mudanyali 2023-10-21 18:45:07 +03:00
parent fb9829c93f
commit 75b3835bed
3 changed files with 138 additions and 39 deletions

View File

@ -16,18 +16,117 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "init.h"
#include "fdt.h"
void fdt_init(fdt_header* fdt) {
// Swap fdt_header values from big endian to little endian
fdt->magic = SWAP_UINT32(fdt->magic);
fdt->totalsize = SWAP_UINT32(fdt->totalsize);
fdt->off_dt_struct = SWAP_UINT32(fdt->off_dt_struct);
fdt->off_dt_strings = SWAP_UINT32(fdt->off_dt_strings);
fdt->off_mem_rsvmap = SWAP_UINT32(fdt->off_mem_rsvmap);
fdt->version = SWAP_UINT32(fdt->version);
fdt->last_comp_version = SWAP_UINT32(fdt->last_comp_version);
fdt->boot_cpuid_phys = SWAP_UINT32(fdt->boot_cpuid_phys);
fdt->size_dt_strings = SWAP_UINT32(fdt->size_dt_strings);
fdt->size_dt_struct = SWAP_UINT32(fdt->size_dt_struct);
size_t _strlen(const char* str) {
size_t len = 0;
while (str[len]) {
len++;
}
return len;
}
void parse_fdt(fdt_header* fdt) {
const char* fdt_strings = (uint32_t)fdt + SWAP_UINT32(fdt->off_dt_strings);
uint32_t* fdt_struct = (uint32_t)fdt + SWAP_UINT32(fdt->off_dt_struct);
const uint32_t struct_size = SWAP_UINT32(fdt->size_dt_struct);
uint32_t* struct_ptr = fdt_struct;
uint32_t name_length = 0;
uint32_t prop_length = 0;
uint32_t prop_name_off = 0;
uint8_t tab_count = 0;
uint8_t first_elem = 0;
while(struct_ptr < fdt_struct + struct_size) {
// Read token
const uint32_t token = SWAP_UINT32(*struct_ptr);
switch(token) {
// The beginning node is followed immediately by its name
case FDT_BEGIN_NODE:
// Advance pointer
struct_ptr++;
// print tabs
for(int i = 0; i < tab_count; ++i) uart_puts(" ");
// increment tab count
tab_count++;
// Calculate the size of the node name
name_length = _strlen(struct_ptr);
// Print node name
if(!name_length) {
uart_puts("/:");
} else {
uart_puts(struct_ptr);
uart_puts(":");
}
uart_putc('\n');
// Advance pointer by size of node name aligned to 4 bytes
struct_ptr += name_length / 4;
break;
// Property
case FDT_PROP:
// Advance pointer
prop_length = *++struct_ptr;
prop_name_off = *++struct_ptr;
// print tabs
for(int i = 0; i < tab_count+1; ++i) uart_puts(" ");
// Print prop name and value
uart_puts(fdt_strings + SWAP_UINT32(prop_name_off));
// Value can be empty
if(prop_length) {
uart_puts(": ");
// Dirty hack to see if the value is a string or a number(s)
// If the first byte of the 4 byte chunk does not fall
// under acceptable ASCII character values, print its
// digits one by one, else just call puts on it since
// it is ***probably*** a string.
first_elem = (char*)(SWAP_UINT32(*(struct_ptr+1)));
// It is probably a number or an array of numbers
if(first_elem < 0x20 || first_elem > 0x7A) {
// Divide length of the property by 4 to get
// the amount of numbers and iterate over them
for(int i = 0; i < SWAP_UINT32(prop_length)/4; ++i) {
uint32_t hex = SWAP_UINT32(*(struct_ptr+1+i));
// Put 0x before to denote it is a hexadecimal number
uart_puts("0x");
// Shift and mask number to get digits
for(int shift = 28; shift >= 0; shift -= 4) {
int digit = (hex >> shift) & 0xF;
int digit_char = (digit<10)?('0'+digit):('A'+digit-10);
uart_putc(digit_char);
}
// There might be more numbers coming so seperate them
uart_puts(" ");
}
} else {
// Its a good old string
uart_puts(struct_ptr+1);
}
}
uart_putc('\n');
struct_ptr += SWAP_UINT32(prop_length) / 4;
break;
// End is followed immediately by next token
case FDT_END_NODE:
--tab_count;
case FDT_NOP:
break;
// There can be only one FDT_END which marks the
// end of FDT
case FDT_END:
return;
}
// Advance pointer
struct_ptr++;
}
}

View File

@ -19,23 +19,34 @@
#ifndef _ASAGIRI_AARCH64_FDT
#define _ASAGIRI_AARCH64_FDT
#define SWAP_UINT32(x) (((x) >> 24) | (((x) & 0x00FF0000) >> 8) | (((x) & 0x0000FF00) << 8) | ((x) << 24))
#define SWAP_UINT32(x) (((x) >> 24) | \
(((x) & 0x00FF0000) >> 8) | \
(((x) & 0x0000FF00) << 8) | \
((x) << 24))
#include "bits/alltypes.h"
typedef struct fdt_header {
uint32_t magic;
uint32_t totalsize;
uint32_t off_dt_struct;
uint32_t off_dt_strings;
uint32_t off_mem_rsvmap;
uint32_t version;
uint32_t last_comp_version;
uint32_t boot_cpuid_phys;
uint32_t size_dt_strings;
uint32_t size_dt_struct;
uint32_t magic; // Magic value identifying FDT
uint32_t totalsize; // Total size of FDT including the header
uint32_t off_dt_struct; // Offset from beginning of the FDT to the structure block
uint32_t off_dt_strings; // Offset from beginning of the FDT to the strings block
uint32_t off_mem_rsvmap; // Offset from beginning of the FDT to the memory reservation map
uint32_t version; // FDT version
uint32_t last_comp_version; // Last compatible version
uint32_t boot_cpuid_phys; // Boot CPU ID
uint32_t size_dt_strings; // Size of the strings block
uint32_t size_dt_struct; // Size of the structure block
} fdt_header;
void fdt_init(fdt_header*);
enum {
FDT_BEGIN_NODE = 0x1,
FDT_END_NODE = 0x2,
FDT_PROP = 0x3,
FDT_NOP = 0x4,
FDT_END = 0x9,
};
void parse_fdt();
#endif

View File

@ -27,27 +27,16 @@
void __attribute__((section (".text.boot"))) _start() {
// Read FDT and convert to little endian
fdt_header* fdt = (fdt_header*)(*(uint32_t*)0x1337);
fdt_init(fdt);
// init uart
uart_init(3);
uart_puts(
"Esselamunaleykum ve rahmetullahi ve berakatu\n"
"Allahin selami uzerine olsun canim kardesim.\n"
"Simdi sana DTBdeki stringleri siraliyorum: \n\n - "
"Simdi sana DTByi siraliyorum:\n\n"
);
// Print char array
char* char_array = (char*)((uint32_t)fdt + fdt->off_dt_strings);
for(int i = 0; i < fdt->size_dt_strings; ++i) {
char c = char_array[i];
switch(c) {
case '\n':
case '\0':
uart_puts("\r\n - ");
break;
default:
uart_putc(c);
}
}
parse_fdt(fdt);
// Test to see if fdt address is correct
asm(
"mov x0, %0\n"