1 /* 2 * Copyright 2021, Haiku, Inc. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include "fdt.h" 8 #include <SupportDefs.h> 9 #include <ByteOrder.h> 10 #include <KernelExport.h> 11 #include <boot/stage2.h> 12 13 extern "C" { 14 #include <libfdt.h> 15 } 16 17 #include "mmu.h" 18 #include "graphics.h" 19 #include "virtio.h" 20 21 22 void* gFdt = NULL; 23 24 25 static void 26 HandleFdt(const void* fdt, int node, uint32_t addressCells, uint32_t sizeCells, 27 uint32_t interruptCells /* from parent node */) 28 { 29 // TODO: handle different field sizes 30 31 const char* device_type = (const char*)fdt_getprop(fdt, node, 32 "device_type", NULL); 33 if (device_type != NULL && strcmp(device_type, "memory") == 0) { 34 gMemBase = (uint8*)fdt64_to_cpu(*((uint64_t*)fdt_getprop(fdt, node, 35 "reg", NULL) + 0)); 36 gTotalMem = fdt64_to_cpu(*((uint64_t*)fdt_getprop(fdt, node, 37 "reg", NULL) + 1)); 38 return; 39 } 40 const char* compatible = (const char*)fdt_getprop(fdt, node, 41 "compatible", NULL); 42 if (compatible == NULL) return; 43 if (strcmp(compatible, "virtio,mmio") == 0) { 44 virtio_register( 45 fdt64_to_cpu(*((uint64_t*)fdt_getprop(fdt, node, "reg", NULL) + 0)), 46 fdt64_to_cpu(*((uint64_t*)fdt_getprop(fdt, node, "reg", NULL) + 1)), 47 fdt32_to_cpu(*((uint32_t*)fdt_getprop(fdt, node, 48 "interrupts-extended", NULL) + 1)) 49 ); 50 } else if (strcmp(compatible, "simple-framebuffer") == 0) { 51 gFramebuf.colors = (uint32_t*)fdt64_to_cpu( 52 *(uint64_t*)fdt_getprop(fdt, node, "reg", NULL)); 53 gFramebuf.stride = fdt32_to_cpu( 54 *(uint32_t*)fdt_getprop(fdt, node, "stride", NULL)) / 4; 55 gFramebuf.width = fdt32_to_cpu( 56 *(uint32_t*)fdt_getprop(fdt, node, "width", NULL)); 57 gFramebuf.height = fdt32_to_cpu( 58 *(uint32_t*)fdt_getprop(fdt, node, "height", NULL)); 59 } 60 } 61 62 63 void 64 fdt_init(void* fdt) 65 { 66 dprintf("FDT: %p\n", fdt); 67 gFdt = fdt; 68 69 int res = fdt_check_header(gFdt); 70 if (res != 0) { 71 panic("Invalid FDT: %s\n", fdt_strerror(res)); 72 } 73 74 dprintf("FDT valid, size: %" B_PRIu32 "\n", fdt_totalsize(gFdt)); 75 76 int node = -1; 77 int depth = 0; 78 while ((node = fdt_next_node(gFdt, node, &depth)) >= 0) { 79 HandleFdt(gFdt, node, 2, 2, 2); 80 } 81 } 82 83 84 void 85 fdt_set_kernel_args() 86 { 87 uint32_t fdtSize = fdt_totalsize(gFdt); 88 89 // libfdt requires 8-byte alignment 90 gKernelArgs.arch_args.fdt = (void*)(addr_t)kernel_args_malloc(fdtSize, 8); 91 92 if (gKernelArgs.arch_args.fdt != NULL) { 93 memcpy(gKernelArgs.arch_args.fdt, gFdt, fdtSize); 94 } else 95 panic("unable to malloc for FDT!\n"); 96 97 dprintf("FDT getting passed to kernel @ %p\n", (void*)gKernelArgs.arch_args.fdt.Pointer()); 98 } 99