dtb_object.cc revision 9538:182d67b5b57a
112027Sjungma@eit.uni-kl.de/*
212027Sjungma@eit.uni-kl.de * Copyright (c) 2013 The Regents of The University of Michigan
312027Sjungma@eit.uni-kl.de * All rights reserved.
412027Sjungma@eit.uni-kl.de *
512027Sjungma@eit.uni-kl.de * Redistribution and use in source and binary forms, with or without
612027Sjungma@eit.uni-kl.de * modification, are permitted provided that the following conditions are
712027Sjungma@eit.uni-kl.de * met: redistributions of source code must retain the above copyright
812027Sjungma@eit.uni-kl.de * notice, this list of conditions and the following disclaimer;
912027Sjungma@eit.uni-kl.de * redistributions in binary form must reproduce the above copyright
1012027Sjungma@eit.uni-kl.de * notice, this list of conditions and the following disclaimer in the
1112027Sjungma@eit.uni-kl.de * documentation and/or other materials provided with the distribution;
1212027Sjungma@eit.uni-kl.de * neither the name of the copyright holders nor the names of its
1312027Sjungma@eit.uni-kl.de * contributors may be used to endorse or promote products derived from
1412027Sjungma@eit.uni-kl.de * this software without specific prior written permission.
1512027Sjungma@eit.uni-kl.de *
1612027Sjungma@eit.uni-kl.de * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1712027Sjungma@eit.uni-kl.de * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1812027Sjungma@eit.uni-kl.de * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1912027Sjungma@eit.uni-kl.de * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2012027Sjungma@eit.uni-kl.de * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2112027Sjungma@eit.uni-kl.de * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2212027Sjungma@eit.uni-kl.de * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2312027Sjungma@eit.uni-kl.de * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2412027Sjungma@eit.uni-kl.de * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2512027Sjungma@eit.uni-kl.de * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2612027Sjungma@eit.uni-kl.de * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2712027Sjungma@eit.uni-kl.de *
2812027Sjungma@eit.uni-kl.de * Authors: Anthony Gutierrez
2912027Sjungma@eit.uni-kl.de */
3012027Sjungma@eit.uni-kl.de
3112027Sjungma@eit.uni-kl.de#include <sys/mman.h>
3212027Sjungma@eit.uni-kl.de#include <err.h>
3312027Sjungma@eit.uni-kl.de#include <unistd.h>
3412027Sjungma@eit.uni-kl.de
3512027Sjungma@eit.uni-kl.de#include <cassert>
3612027Sjungma@eit.uni-kl.de
3712027Sjungma@eit.uni-kl.de#include "base/loader/dtb_object.hh"
3812027Sjungma@eit.uni-kl.de#include "fdt.h"
3912027Sjungma@eit.uni-kl.de#include "libfdt.h"
4012027Sjungma@eit.uni-kl.de
4112027Sjungma@eit.uni-kl.deObjectFile *
4212027Sjungma@eit.uni-kl.deDtbObject::tryFile(const std::string &fname, int fd, size_t len, uint8_t *data)
4312027Sjungma@eit.uni-kl.de{
4412027Sjungma@eit.uni-kl.de    // Check if this is a FDT file by looking for magic number
4512027Sjungma@eit.uni-kl.de    if (fdt_magic((void*)data) == FDT_MAGIC) {
4612027Sjungma@eit.uni-kl.de        return new DtbObject(fname, fd, len, data,
4712027Sjungma@eit.uni-kl.de                             ObjectFile::UnknownArch, ObjectFile::UnknownOpSys);
4812027Sjungma@eit.uni-kl.de    } else {
4912027Sjungma@eit.uni-kl.de        return NULL;
5012027Sjungma@eit.uni-kl.de    }
5112027Sjungma@eit.uni-kl.de}
5212027Sjungma@eit.uni-kl.de
5312027Sjungma@eit.uni-kl.deDtbObject::DtbObject(const std::string &_filename, int _fd,
5412027Sjungma@eit.uni-kl.de                     size_t _len, uint8_t *_data,
5512027Sjungma@eit.uni-kl.de                     Arch _arch, OpSys _opSys)
5612027Sjungma@eit.uni-kl.de    : ObjectFile(_filename, _fd, _len, _data, _arch, _opSys)
5712027Sjungma@eit.uni-kl.de{
5812027Sjungma@eit.uni-kl.de    text.baseAddr = 0;
5912027Sjungma@eit.uni-kl.de    text.size = len;
6012027Sjungma@eit.uni-kl.de    text.fileImage = fileData;
6112027Sjungma@eit.uni-kl.de
6212027Sjungma@eit.uni-kl.de    data.baseAddr = 0;
6312027Sjungma@eit.uni-kl.de    data.size = 0;
6412027Sjungma@eit.uni-kl.de    data.fileImage = NULL;
6512027Sjungma@eit.uni-kl.de
6612027Sjungma@eit.uni-kl.de    bss.baseAddr = 0;
6712027Sjungma@eit.uni-kl.de    bss.size = 0;
6812027Sjungma@eit.uni-kl.de    bss.fileImage = NULL;
6912027Sjungma@eit.uni-kl.de
7012027Sjungma@eit.uni-kl.de    fileDataMmapped = true;
7112027Sjungma@eit.uni-kl.de}
7212027Sjungma@eit.uni-kl.de
7312027Sjungma@eit.uni-kl.deDtbObject::~DtbObject()
7412027Sjungma@eit.uni-kl.de{
7512027Sjungma@eit.uni-kl.de    if (descriptor >= 0) {
7612027Sjungma@eit.uni-kl.de        ::close(descriptor);
7712027Sjungma@eit.uni-kl.de        descriptor = -1;
7812027Sjungma@eit.uni-kl.de    }
7912027Sjungma@eit.uni-kl.de
8012027Sjungma@eit.uni-kl.de    // Make sure to clean up memory properly depending
8112027Sjungma@eit.uni-kl.de    // on how buffer was allocated.
8212027Sjungma@eit.uni-kl.de    if (fileData && !fileDataMmapped) {
8312027Sjungma@eit.uni-kl.de        delete [] fileData;
8412027Sjungma@eit.uni-kl.de        fileData = NULL;
8512027Sjungma@eit.uni-kl.de    } else if (fileData) {
8612027Sjungma@eit.uni-kl.de        munmap(fileData, len);
8712027Sjungma@eit.uni-kl.de        fileData = NULL;
8812027Sjungma@eit.uni-kl.de    }
8912027Sjungma@eit.uni-kl.de}
9012027Sjungma@eit.uni-kl.de
9112027Sjungma@eit.uni-kl.debool
9212027Sjungma@eit.uni-kl.deDtbObject::addBootCmdLine(const char* _args, size_t len)
9312027Sjungma@eit.uni-kl.de{
9412027Sjungma@eit.uni-kl.de    const char* root_path = "/";
9512027Sjungma@eit.uni-kl.de    const char* node_name = "chosen";
9612027Sjungma@eit.uni-kl.de    const char* full_path_node_name = "/chosen";
9712027Sjungma@eit.uni-kl.de    const char* property_name = "bootargs";
9812027Sjungma@eit.uni-kl.de
9912027Sjungma@eit.uni-kl.de    // Make a new buffer that has extra space to add nodes/properties
10012027Sjungma@eit.uni-kl.de    int newLen = 2*this->len;
10112027Sjungma@eit.uni-kl.de    uint8_t* fdt_buf_w_space = new uint8_t[newLen];
10212027Sjungma@eit.uni-kl.de    // Copy and unpack flattened device tree into new buffer
10312027Sjungma@eit.uni-kl.de    int ret = fdt_open_into((void*)fileData, (void*)fdt_buf_w_space, (newLen));
10412027Sjungma@eit.uni-kl.de    if (ret < 0) {
10512027Sjungma@eit.uni-kl.de        warn("Error resizing buffer of flattened device tree, "
10612027Sjungma@eit.uni-kl.de             "errno: %d\n", ret);
10712027Sjungma@eit.uni-kl.de        delete [] fdt_buf_w_space;
10812027Sjungma@eit.uni-kl.de        return false;
10912027Sjungma@eit.uni-kl.de    }
11012027Sjungma@eit.uni-kl.de
11112027Sjungma@eit.uni-kl.de    // First try finding the /chosen node in the dtb
11212027Sjungma@eit.uni-kl.de    int offset = fdt_path_offset((void*)fdt_buf_w_space, full_path_node_name);
11312027Sjungma@eit.uni-kl.de    if (offset < 0) {
11412027Sjungma@eit.uni-kl.de        // try adding the node by walking dtb tree to proper insertion point
11512027Sjungma@eit.uni-kl.de        offset = fdt_path_offset((void*)fdt_buf_w_space, root_path);
11612027Sjungma@eit.uni-kl.de        offset = fdt_add_subnode((void*)fdt_buf_w_space, offset, node_name);
11712027Sjungma@eit.uni-kl.de        offset = fdt_path_offset((void*)fdt_buf_w_space, full_path_node_name);
11812027Sjungma@eit.uni-kl.de        if (offset < 0) {
11912027Sjungma@eit.uni-kl.de            warn("Error finding or adding \"chosen\" subnode to flattened "
12012027Sjungma@eit.uni-kl.de                 "device tree, errno: %d\n", offset);
12112027Sjungma@eit.uni-kl.de            delete [] fdt_buf_w_space;
12212027Sjungma@eit.uni-kl.de            return false;
12312027Sjungma@eit.uni-kl.de        }
12412027Sjungma@eit.uni-kl.de    }
12512027Sjungma@eit.uni-kl.de
12612027Sjungma@eit.uni-kl.de    // Set the bootargs property in the /chosen node
12712027Sjungma@eit.uni-kl.de    ret = fdt_setprop((void*)fdt_buf_w_space, offset, property_name,
12812027Sjungma@eit.uni-kl.de                      (const void*)_args, len+1);
12912027Sjungma@eit.uni-kl.de    if (ret < 0) {
13012027Sjungma@eit.uni-kl.de        warn("Error setting \"bootargs\" property to flattened device tree, "
13112027Sjungma@eit.uni-kl.de             "errno: %d\n", ret);
13212027Sjungma@eit.uni-kl.de        delete [] fdt_buf_w_space;
133        return false;
134    }
135
136    // Repack the dtb for kernel use
137    ret = fdt_pack((void*)fdt_buf_w_space);
138    if (ret < 0) {
139        warn("Error re-packing flattened device tree structure, "
140             "errno: %d\n", ret);
141        delete [] fdt_buf_w_space;
142        return false;
143    }
144
145    text.size = newLen;
146    text.fileImage = fdt_buf_w_space;
147
148    // clean up old buffer and set to new fdt blob
149    munmap(fileData, this->len);
150    fileData = fdt_buf_w_space;
151    fileDataMmapped = false;
152    this->len = newLen;
153
154    return true;
155}
156
157bool
158DtbObject::loadGlobalSymbols(SymbolTable *symtab, Addr addrMask)
159{
160    // nothing to do here
161    return false;
162}
163
164bool
165DtbObject::loadLocalSymbols(SymbolTable *symtab, Addr addrMask)
166{
167    // nothing to do here
168    return false;
169}
170