dtb_object.cc revision 9538
19538Satgutier@umich.edu/* 29538Satgutier@umich.edu * Copyright (c) 2013 The Regents of The University of Michigan 39538Satgutier@umich.edu * All rights reserved. 49538Satgutier@umich.edu * 59538Satgutier@umich.edu * Redistribution and use in source and binary forms, with or without 69538Satgutier@umich.edu * modification, are permitted provided that the following conditions are 79538Satgutier@umich.edu * met: redistributions of source code must retain the above copyright 89538Satgutier@umich.edu * notice, this list of conditions and the following disclaimer; 99538Satgutier@umich.edu * redistributions in binary form must reproduce the above copyright 109538Satgutier@umich.edu * notice, this list of conditions and the following disclaimer in the 119538Satgutier@umich.edu * documentation and/or other materials provided with the distribution; 129538Satgutier@umich.edu * neither the name of the copyright holders nor the names of its 139538Satgutier@umich.edu * contributors may be used to endorse or promote products derived from 149538Satgutier@umich.edu * this software without specific prior written permission. 159538Satgutier@umich.edu * 169538Satgutier@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 179538Satgutier@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 189538Satgutier@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 199538Satgutier@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 209538Satgutier@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 219538Satgutier@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 229538Satgutier@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 239538Satgutier@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 249538Satgutier@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 259538Satgutier@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 269538Satgutier@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 279538Satgutier@umich.edu * 289538Satgutier@umich.edu * Authors: Anthony Gutierrez 299538Satgutier@umich.edu */ 309538Satgutier@umich.edu 319538Satgutier@umich.edu#include <sys/mman.h> 329538Satgutier@umich.edu#include <err.h> 339538Satgutier@umich.edu#include <unistd.h> 349538Satgutier@umich.edu 359538Satgutier@umich.edu#include <cassert> 369538Satgutier@umich.edu 379538Satgutier@umich.edu#include "base/loader/dtb_object.hh" 389538Satgutier@umich.edu#include "fdt.h" 399538Satgutier@umich.edu#include "libfdt.h" 409538Satgutier@umich.edu 419538Satgutier@umich.eduObjectFile * 429538Satgutier@umich.eduDtbObject::tryFile(const std::string &fname, int fd, size_t len, uint8_t *data) 439538Satgutier@umich.edu{ 449538Satgutier@umich.edu // Check if this is a FDT file by looking for magic number 459538Satgutier@umich.edu if (fdt_magic((void*)data) == FDT_MAGIC) { 469538Satgutier@umich.edu return new DtbObject(fname, fd, len, data, 479538Satgutier@umich.edu ObjectFile::UnknownArch, ObjectFile::UnknownOpSys); 489538Satgutier@umich.edu } else { 499538Satgutier@umich.edu return NULL; 509538Satgutier@umich.edu } 519538Satgutier@umich.edu} 529538Satgutier@umich.edu 539538Satgutier@umich.eduDtbObject::DtbObject(const std::string &_filename, int _fd, 549538Satgutier@umich.edu size_t _len, uint8_t *_data, 559538Satgutier@umich.edu Arch _arch, OpSys _opSys) 569538Satgutier@umich.edu : ObjectFile(_filename, _fd, _len, _data, _arch, _opSys) 579538Satgutier@umich.edu{ 589538Satgutier@umich.edu text.baseAddr = 0; 599538Satgutier@umich.edu text.size = len; 609538Satgutier@umich.edu text.fileImage = fileData; 619538Satgutier@umich.edu 629538Satgutier@umich.edu data.baseAddr = 0; 639538Satgutier@umich.edu data.size = 0; 649538Satgutier@umich.edu data.fileImage = NULL; 659538Satgutier@umich.edu 669538Satgutier@umich.edu bss.baseAddr = 0; 679538Satgutier@umich.edu bss.size = 0; 689538Satgutier@umich.edu bss.fileImage = NULL; 699538Satgutier@umich.edu 709538Satgutier@umich.edu fileDataMmapped = true; 719538Satgutier@umich.edu} 729538Satgutier@umich.edu 739538Satgutier@umich.eduDtbObject::~DtbObject() 749538Satgutier@umich.edu{ 759538Satgutier@umich.edu if (descriptor >= 0) { 769538Satgutier@umich.edu ::close(descriptor); 779538Satgutier@umich.edu descriptor = -1; 789538Satgutier@umich.edu } 799538Satgutier@umich.edu 809538Satgutier@umich.edu // Make sure to clean up memory properly depending 819538Satgutier@umich.edu // on how buffer was allocated. 829538Satgutier@umich.edu if (fileData && !fileDataMmapped) { 839538Satgutier@umich.edu delete [] fileData; 849538Satgutier@umich.edu fileData = NULL; 859538Satgutier@umich.edu } else if (fileData) { 869538Satgutier@umich.edu munmap(fileData, len); 879538Satgutier@umich.edu fileData = NULL; 889538Satgutier@umich.edu } 899538Satgutier@umich.edu} 909538Satgutier@umich.edu 919538Satgutier@umich.edubool 929538Satgutier@umich.eduDtbObject::addBootCmdLine(const char* _args, size_t len) 939538Satgutier@umich.edu{ 949538Satgutier@umich.edu const char* root_path = "/"; 959538Satgutier@umich.edu const char* node_name = "chosen"; 969538Satgutier@umich.edu const char* full_path_node_name = "/chosen"; 979538Satgutier@umich.edu const char* property_name = "bootargs"; 989538Satgutier@umich.edu 999538Satgutier@umich.edu // Make a new buffer that has extra space to add nodes/properties 1009538Satgutier@umich.edu int newLen = 2*this->len; 1019538Satgutier@umich.edu uint8_t* fdt_buf_w_space = new uint8_t[newLen]; 1029538Satgutier@umich.edu // Copy and unpack flattened device tree into new buffer 1039538Satgutier@umich.edu int ret = fdt_open_into((void*)fileData, (void*)fdt_buf_w_space, (newLen)); 1049538Satgutier@umich.edu if (ret < 0) { 1059538Satgutier@umich.edu warn("Error resizing buffer of flattened device tree, " 1069538Satgutier@umich.edu "errno: %d\n", ret); 1079538Satgutier@umich.edu delete [] fdt_buf_w_space; 1089538Satgutier@umich.edu return false; 1099538Satgutier@umich.edu } 1109538Satgutier@umich.edu 1119538Satgutier@umich.edu // First try finding the /chosen node in the dtb 1129538Satgutier@umich.edu int offset = fdt_path_offset((void*)fdt_buf_w_space, full_path_node_name); 1139538Satgutier@umich.edu if (offset < 0) { 1149538Satgutier@umich.edu // try adding the node by walking dtb tree to proper insertion point 1159538Satgutier@umich.edu offset = fdt_path_offset((void*)fdt_buf_w_space, root_path); 1169538Satgutier@umich.edu offset = fdt_add_subnode((void*)fdt_buf_w_space, offset, node_name); 1179538Satgutier@umich.edu offset = fdt_path_offset((void*)fdt_buf_w_space, full_path_node_name); 1189538Satgutier@umich.edu if (offset < 0) { 1199538Satgutier@umich.edu warn("Error finding or adding \"chosen\" subnode to flattened " 1209538Satgutier@umich.edu "device tree, errno: %d\n", offset); 1219538Satgutier@umich.edu delete [] fdt_buf_w_space; 1229538Satgutier@umich.edu return false; 1239538Satgutier@umich.edu } 1249538Satgutier@umich.edu } 1259538Satgutier@umich.edu 1269538Satgutier@umich.edu // Set the bootargs property in the /chosen node 1279538Satgutier@umich.edu ret = fdt_setprop((void*)fdt_buf_w_space, offset, property_name, 1289538Satgutier@umich.edu (const void*)_args, len+1); 1299538Satgutier@umich.edu if (ret < 0) { 1309538Satgutier@umich.edu warn("Error setting \"bootargs\" property to flattened device tree, " 1319538Satgutier@umich.edu "errno: %d\n", ret); 1329538Satgutier@umich.edu delete [] fdt_buf_w_space; 1339538Satgutier@umich.edu return false; 1349538Satgutier@umich.edu } 1359538Satgutier@umich.edu 1369538Satgutier@umich.edu // Repack the dtb for kernel use 1379538Satgutier@umich.edu ret = fdt_pack((void*)fdt_buf_w_space); 1389538Satgutier@umich.edu if (ret < 0) { 1399538Satgutier@umich.edu warn("Error re-packing flattened device tree structure, " 1409538Satgutier@umich.edu "errno: %d\n", ret); 1419538Satgutier@umich.edu delete [] fdt_buf_w_space; 1429538Satgutier@umich.edu return false; 1439538Satgutier@umich.edu } 1449538Satgutier@umich.edu 1459538Satgutier@umich.edu text.size = newLen; 1469538Satgutier@umich.edu text.fileImage = fdt_buf_w_space; 1479538Satgutier@umich.edu 1489538Satgutier@umich.edu // clean up old buffer and set to new fdt blob 1499538Satgutier@umich.edu munmap(fileData, this->len); 1509538Satgutier@umich.edu fileData = fdt_buf_w_space; 1519538Satgutier@umich.edu fileDataMmapped = false; 1529538Satgutier@umich.edu this->len = newLen; 1539538Satgutier@umich.edu 1549538Satgutier@umich.edu return true; 1559538Satgutier@umich.edu} 1569538Satgutier@umich.edu 1579538Satgutier@umich.edubool 1589538Satgutier@umich.eduDtbObject::loadGlobalSymbols(SymbolTable *symtab, Addr addrMask) 1599538Satgutier@umich.edu{ 1609538Satgutier@umich.edu // nothing to do here 1619538Satgutier@umich.edu return false; 1629538Satgutier@umich.edu} 1639538Satgutier@umich.edu 1649538Satgutier@umich.edubool 1659538Satgutier@umich.eduDtbObject::loadLocalSymbols(SymbolTable *symtab, Addr addrMask) 1669538Satgutier@umich.edu{ 1679538Satgutier@umich.edu // nothing to do here 1689538Satgutier@umich.edu return false; 1699538Satgutier@umich.edu} 170