Sateallia ae5570ba77 revert ae2f9301c01a20f16ae764c518916de9b3ae0ddf
revert Refactor fdt_init in arch/aarch64
2023-10-22 14:22:56 -07:00

100 lines
3.2 KiB
C

/**
* fdt implementation of Asagiri
* Copyright (C) 2023 Asagiri contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <fdt.h>
#include <string.h>
fdt_header* fdt;
void fdt_init() {
fdt = (fdt_header*)(*(uint32_t*)0x1337);
}
fdt_prop fdt_get_prop(uint32_t* addr) {
return (fdt_prop){
SWAP_UINT32(*addr),
SWAP_UINT32(*(addr+1)),
addr+2
};
}
uint32_t* fdt_get_addr(const char* path) {
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;
uint32_t* lastaddr = 0;
char path_copy[strlen(path)+1];
strcpy(path_copy, path);
char* name = strtok(path_copy, "/");
while(name && 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++;
// check if we are in the token we want
if(!strcmp((char*)struct_ptr, name)) {
name = strtok(0, "/");
lastaddr = struct_ptr;
}
// Calculate the size of the node name
name_length = strlen((char*)struct_ptr);
// 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;
// check if we are in the token we want
if(!strcmp(fdt_strings + SWAP_UINT32(prop_name_off), name)) {
return struct_ptr-1;
}
// Advance pointer
struct_ptr += SWAP_UINT32(prop_length) / 4;
break;
// End is followed immediately by next token
case FDT_END_NODE:
case FDT_NOP:
break;
// There can be only one FDT_END which marks the
// end of FDT
case FDT_END:
return 0;
}
// Advance pointer
struct_ptr++;
}
return lastaddr;
}