ofwfdt.c revision 346302
1279799Snwhitehorn/*- 2279799Snwhitehorn * Copyright (C) 2014-2015 Nathan Whitehorn 3279799Snwhitehorn * All rights reserved. 4279799Snwhitehorn * 5279799Snwhitehorn * Redistribution and use in source and binary forms, with or without 6279799Snwhitehorn * modification, are permitted provided that the following conditions 7279799Snwhitehorn * are met: 8279799Snwhitehorn * 1. Redistributions of source code must retain the above copyright 9279799Snwhitehorn * notice, this list of conditions and the following disclaimer. 10279799Snwhitehorn * 2. Redistributions in binary form must reproduce the above copyright 11279799Snwhitehorn * notice, this list of conditions and the following disclaimer in the 12279799Snwhitehorn * documentation and/or other materials provided with the distribution. 13279799Snwhitehorn * 14279799Snwhitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15279799Snwhitehorn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16279799Snwhitehorn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17279799Snwhitehorn * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18279799Snwhitehorn * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19279799Snwhitehorn * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20279799Snwhitehorn * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21279799Snwhitehorn * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 22279799Snwhitehorn * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23279799Snwhitehorn * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24279799Snwhitehorn */ 25279799Snwhitehorn 26279799Snwhitehorn#include <sys/cdefs.h> 27279799Snwhitehorn__FBSDID("$FreeBSD: stable/11/stand/powerpc/ofw/ofwfdt.c 346302 2019-04-16 21:01:07Z kevans $"); 28279799Snwhitehorn 29279799Snwhitehorn#include <stand.h> 30279799Snwhitehorn#include <sys/param.h> 31279799Snwhitehorn#include <fdt_platform.h> 32279799Snwhitehorn#include <openfirm.h> 33279799Snwhitehorn#include <libfdt.h> 34279799Snwhitehorn#include "bootstrap.h" 35279799Snwhitehorn 36302312Snwhitehornextern int command_fdt_internal(int argc, char *argv[]); 37302312Snwhitehorn 38279799Snwhitehornstatic int 39279799SnwhitehornOF_hasprop(phandle_t node, const char *prop) 40279799Snwhitehorn{ 41302312Snwhitehorn return (OF_getproplen(node, (char *)prop) > 0); 42279799Snwhitehorn} 43279799Snwhitehorn 44279799Snwhitehornstatic void 45279799Snwhitehornadd_node_to_fdt(void *buffer, phandle_t node, int fdt_offset) 46279799Snwhitehorn{ 47302312Snwhitehorn int i, child_offset, error; 48302312Snwhitehorn char name[255], *lastprop, *subname; 49279799Snwhitehorn void *propbuf; 50302312Snwhitehorn ssize_t proplen; 51279799Snwhitehorn 52279799Snwhitehorn lastprop = NULL; 53279799Snwhitehorn while (OF_nextprop(node, lastprop, name) > 0) { 54279799Snwhitehorn proplen = OF_getproplen(node, name); 55302312Snwhitehorn 56302312Snwhitehorn /* Detect and correct for errors and strangeness */ 57302312Snwhitehorn if (proplen < 0) 58302312Snwhitehorn proplen = 0; 59302312Snwhitehorn if (proplen > 1024) 60302312Snwhitehorn proplen = 1024; 61302312Snwhitehorn 62279799Snwhitehorn propbuf = malloc(proplen); 63302312Snwhitehorn if (propbuf == NULL) { 64302312Snwhitehorn printf("Cannot allocate memory for prop %s\n", name); 65302312Snwhitehorn return; 66302312Snwhitehorn } 67279799Snwhitehorn OF_getprop(node, name, propbuf, proplen); 68279799Snwhitehorn error = fdt_setprop(buffer, fdt_offset, name, propbuf, proplen); 69279799Snwhitehorn free(propbuf); 70279799Snwhitehorn lastprop = name; 71279799Snwhitehorn if (error) 72279799Snwhitehorn printf("Error %d adding property %s to " 73279799Snwhitehorn "node %d\n", error, name, fdt_offset); 74279799Snwhitehorn } 75279799Snwhitehorn 76279799Snwhitehorn if (!OF_hasprop(node, "phandle") && !OF_hasprop(node, "linux,phandle") 77279799Snwhitehorn && !OF_hasprop(node, "ibm,phandle")) 78279799Snwhitehorn fdt_setprop(buffer, fdt_offset, "phandle", &node, sizeof(node)); 79279799Snwhitehorn 80302312Snwhitehorn for (node = OF_child(node); node > 0; node = OF_peer(node)) { 81279799Snwhitehorn OF_package_to_path(node, name, sizeof(name)); 82279799Snwhitehorn subname = strrchr(name, '/'); 83279799Snwhitehorn subname++; 84279799Snwhitehorn child_offset = fdt_add_subnode(buffer, fdt_offset, subname); 85279799Snwhitehorn if (child_offset < 0) { 86279799Snwhitehorn printf("Error %d adding node %s (%s), skipping\n", 87279799Snwhitehorn child_offset, name, subname); 88279799Snwhitehorn continue; 89279799Snwhitehorn } 90279799Snwhitehorn 91279799Snwhitehorn add_node_to_fdt(buffer, node, child_offset); 92302312Snwhitehorn } 93279799Snwhitehorn} 94279799Snwhitehorn 95279799Snwhitehornstatic void 96279799Snwhitehornofwfdt_fixups(void *fdtp) 97279799Snwhitehorn{ 98279799Snwhitehorn int offset, len, i; 99279799Snwhitehorn phandle_t node; 100279799Snwhitehorn ihandle_t rtas; 101279799Snwhitehorn const void *prop; 102279799Snwhitehorn 103279799Snwhitehorn /* 104279799Snwhitehorn * Instantiate and add reservations for RTAS state if present 105279799Snwhitehorn */ 106279799Snwhitehorn 107279799Snwhitehorn offset = fdt_path_offset(fdtp, "/rtas"); 108279799Snwhitehorn if (offset > 0) { 109279799Snwhitehorn uint32_t base; 110279799Snwhitehorn void *rtasmem; 111279799Snwhitehorn char path[255]; 112279799Snwhitehorn 113279799Snwhitehorn node = OF_finddevice("/rtas"); 114279799Snwhitehorn OF_package_to_path(node, path, sizeof(path)); 115279799Snwhitehorn OF_getprop(node, "rtas-size", &len, sizeof(len)); 116279799Snwhitehorn 117279799Snwhitehorn /* Allocate memory */ 118279799Snwhitehorn rtasmem = OF_claim(0, len, 4096); 119279799Snwhitehorn 120279799Snwhitehorn /* Instantiate RTAS */ 121279799Snwhitehorn rtas = OF_open(path); 122279799Snwhitehorn base = 0; 123279799Snwhitehorn OF_call_method("instantiate-rtas", rtas, 1, 1, (cell_t)rtas, 124279799Snwhitehorn &base); 125279799Snwhitehorn 126279799Snwhitehorn /* Store info to FDT using Linux convention */ 127279799Snwhitehorn base = cpu_to_fdt32(base); 128279799Snwhitehorn fdt_setprop(fdtp, offset, "linux,rtas-entry", &base, 129279799Snwhitehorn sizeof(base)); 130279799Snwhitehorn base = cpu_to_fdt32((uint32_t)rtasmem); 131279799Snwhitehorn offset = fdt_path_offset(fdtp, "/rtas"); 132279799Snwhitehorn fdt_setprop(fdtp, offset, "linux,rtas-base", &base, 133279799Snwhitehorn sizeof(base)); 134279799Snwhitehorn 135279799Snwhitehorn /* Mark RTAS private data area reserved */ 136279799Snwhitehorn fdt_add_mem_rsv(fdtp, base, len); 137279799Snwhitehorn } else { 138279799Snwhitehorn /* 139302312Snwhitehorn * Remove /memory/available properties, which reflect long-gone 140302312Snwhitehorn * OF state. Note that this doesn't work if we need RTAS still, 141302312Snwhitehorn * since that's part of the firmware. 142279799Snwhitehorn */ 143279799Snwhitehorn offset = fdt_path_offset(fdtp, "/memory@0"); 144279799Snwhitehorn if (offset > 0) 145279799Snwhitehorn fdt_delprop(fdtp, offset, "available"); 146279799Snwhitehorn } 147279799Snwhitehorn 148302312Snwhitehorn 149279799Snwhitehorn /* 150279799Snwhitehorn * Convert stored ihandles under /chosen to xref phandles 151279799Snwhitehorn */ 152279799Snwhitehorn offset = fdt_path_offset(fdtp, "/chosen"); 153279799Snwhitehorn if (offset > 0) { 154279799Snwhitehorn const char *chosenprops[] = {"stdout", "stdin", "mmu", "cpu", 155279799Snwhitehorn NULL}; 156279799Snwhitehorn const uint32_t *ihand; 157279799Snwhitehorn for (i = 0; chosenprops[i] != NULL; i++) { 158279799Snwhitehorn ihand = fdt_getprop(fdtp, offset, chosenprops[i], &len); 159279799Snwhitehorn if (ihand != NULL && len == sizeof(*ihand)) { 160279799Snwhitehorn node = OF_instance_to_package( 161279799Snwhitehorn fdt32_to_cpu(*ihand)); 162279799Snwhitehorn if (OF_hasprop(node, "phandle")) 163279799Snwhitehorn OF_getprop(node, "phandle", &node, 164279799Snwhitehorn sizeof(node)); 165279799Snwhitehorn else if (OF_hasprop(node, "linux,phandle")) 166279799Snwhitehorn OF_getprop(node, "linux,phandle", &node, 167279799Snwhitehorn sizeof(node)); 168279799Snwhitehorn else if (OF_hasprop(node, "ibm,phandle")) 169279799Snwhitehorn OF_getprop(node, "ibm,phandle", &node, 170279799Snwhitehorn sizeof(node)); 171279799Snwhitehorn node = cpu_to_fdt32(node); 172302312Snwhitehorn fdt_setprop(fdtp, offset, chosenprops[i], &node, 173302312Snwhitehorn sizeof(node)); 174279799Snwhitehorn } 175279799Snwhitehorn 176279799Snwhitehorn /* Refind node in case it moved */ 177279799Snwhitehorn offset = fdt_path_offset(fdtp, "/chosen"); 178279799Snwhitehorn } 179279799Snwhitehorn } 180279799Snwhitehorn} 181279799Snwhitehorn 182279799Snwhitehornint 183279799Snwhitehornfdt_platform_load_dtb(void) 184279799Snwhitehorn{ 185279799Snwhitehorn void *buffer; 186279799Snwhitehorn size_t buflen = 409600; 187279799Snwhitehorn 188279799Snwhitehorn buffer = malloc(buflen); 189279799Snwhitehorn fdt_create_empty_tree(buffer, buflen); 190279799Snwhitehorn add_node_to_fdt(buffer, OF_peer(0), fdt_path_offset(buffer, "/")); 191279799Snwhitehorn ofwfdt_fixups(buffer); 192279799Snwhitehorn fdt_pack(buffer); 193279799Snwhitehorn 194279799Snwhitehorn fdt_load_dtb_addr(buffer); 195279799Snwhitehorn free(buffer); 196279799Snwhitehorn 197279799Snwhitehorn return (0); 198279799Snwhitehorn} 199279799Snwhitehorn 200279799Snwhitehornvoid 201346302Skevansfdt_platform_load_overlays(void) 202346302Skevans{ 203346302Skevans 204346302Skevans} 205346302Skevans 206346302Skevansvoid 207279799Snwhitehornfdt_platform_fixups(void) 208279799Snwhitehorn{ 209279799Snwhitehorn 210279799Snwhitehorn} 211279799Snwhitehorn 212279799Snwhitehornstatic int 213279799Snwhitehorncommand_fdt(int argc, char *argv[]) 214279799Snwhitehorn{ 215279799Snwhitehorn 216279799Snwhitehorn return (command_fdt_internal(argc, argv)); 217279799Snwhitehorn} 218279799Snwhitehorn 219279799SnwhitehornCOMMAND_SET(fdt, "fdt", "flattened device tree handling", command_fdt); 220279799Snwhitehorn 221