base: remove header file to prevent a macro name collision
[gem5.git] / src / base / loader / dtb_object.cc
1 /*
2 * Copyright (c) 2013 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Anthony Gutierrez
29 */
30
31 #include "base/loader/dtb_object.hh"
32
33 #include <sys/mman.h>
34 #include <unistd.h>
35
36 #include <cassert>
37
38 #include "sim/byteswap.hh"
39 #include "fdt.h"
40 #include "libfdt.h"
41
42 ObjectFile *
43 DtbObject::tryFile(const std::string &fname, size_t len, uint8_t *data)
44 {
45 // Check if this is a FDT file by looking for magic number
46 if (fdt_magic((void*)data) == FDT_MAGIC) {
47 return new DtbObject(fname, len, data,
48 ObjectFile::UnknownArch, ObjectFile::UnknownOpSys);
49 } else {
50 return NULL;
51 }
52 }
53
54 DtbObject::DtbObject(const std::string &_filename, size_t _len, uint8_t *_data,
55 Arch _arch, OpSys _opSys)
56 : ObjectFile(_filename, _len, _data, _arch, _opSys)
57 {
58 text.baseAddr = 0;
59 text.size = len;
60 text.fileImage = fileData;
61
62 data.baseAddr = 0;
63 data.size = 0;
64 data.fileImage = NULL;
65
66 bss.baseAddr = 0;
67 bss.size = 0;
68 bss.fileImage = NULL;
69
70 fileDataMmapped = true;
71 }
72
73 DtbObject::~DtbObject()
74 {
75 // Make sure to clean up memory properly depending
76 // on how buffer was allocated.
77 if (fileData && !fileDataMmapped) {
78 delete [] fileData;
79 fileData = NULL;
80 } else if (fileData) {
81 munmap(fileData, len);
82 fileData = NULL;
83 }
84 }
85
86 bool
87 DtbObject::addBootCmdLine(const char* _args, size_t len)
88 {
89 const char* root_path = "/";
90 const char* node_name = "chosen";
91 const char* full_path_node_name = "/chosen";
92 const char* property_name = "bootargs";
93
94 // Make a new buffer that has extra space to add nodes/properties
95 int newLen = 2*this->len;
96 uint8_t* fdt_buf_w_space = new uint8_t[newLen];
97 // Copy and unpack flattened device tree into new buffer
98 int ret = fdt_open_into((void*)fileData, (void*)fdt_buf_w_space, (newLen));
99 if (ret < 0) {
100 warn("Error resizing buffer of flattened device tree, "
101 "errno: %d\n", ret);
102 delete [] fdt_buf_w_space;
103 return false;
104 }
105
106 // First try finding the /chosen node in the dtb
107 int offset = fdt_path_offset((void*)fdt_buf_w_space, full_path_node_name);
108 if (offset < 0) {
109 // try adding the node by walking dtb tree to proper insertion point
110 offset = fdt_path_offset((void*)fdt_buf_w_space, root_path);
111 offset = fdt_add_subnode((void*)fdt_buf_w_space, offset, node_name);
112 // if we successfully add the subnode, get the offset
113 if (offset >= 0)
114 offset = fdt_path_offset((void*)fdt_buf_w_space, full_path_node_name);
115
116 if (offset < 0) {
117 warn("Error finding or adding \"chosen\" subnode to flattened "
118 "device tree, errno: %d\n", offset);
119 delete [] fdt_buf_w_space;
120 return false;
121 }
122 }
123
124 // Set the bootargs property in the /chosen node
125 ret = fdt_setprop((void*)fdt_buf_w_space, offset, property_name,
126 (const void*)_args, len+1);
127 if (ret < 0) {
128 warn("Error setting \"bootargs\" property to flattened device tree, "
129 "errno: %d\n", ret);
130 delete [] fdt_buf_w_space;
131 return false;
132 }
133
134 // Repack the dtb for kernel use
135 ret = fdt_pack((void*)fdt_buf_w_space);
136 if (ret < 0) {
137 warn("Error re-packing flattened device tree structure, "
138 "errno: %d\n", ret);
139 delete [] fdt_buf_w_space;
140 return false;
141 }
142
143 text.size = newLen;
144 text.fileImage = fdt_buf_w_space;
145
146 // clean up old buffer and set to new fdt blob
147 munmap(fileData, this->len);
148 fileData = fdt_buf_w_space;
149 fileDataMmapped = false;
150 this->len = newLen;
151
152 return true;
153 }
154
155 Addr
156 DtbObject::findReleaseAddr()
157 {
158 void *fd = (void*)fileData;
159
160 int offset = fdt_path_offset(fd, "/cpus/cpu@0");
161 int len;
162
163 const void* temp = fdt_getprop(fd, offset, "cpu-release-addr", &len);
164 Addr rel_addr = 0;
165
166 if (len > 3)
167 rel_addr = betoh(*static_cast<const uint32_t*>(temp));
168 if (len == 8)
169 rel_addr = (rel_addr << 32) | betoh(*(static_cast<const uint32_t*>(temp)+1));
170
171 return rel_addr;
172 }
173
174 bool
175 DtbObject::loadAllSymbols(SymbolTable *symtab, Addr base, Addr offset,
176 Addr addr_mask)
177 {
178 return false;
179 }
180
181 bool
182 DtbObject::loadGlobalSymbols(SymbolTable *symtab, Addr base, Addr offset,
183 Addr addr_mask)
184 {
185 // nothing to do here
186 return false;
187 }
188
189 bool
190 DtbObject::loadLocalSymbols(SymbolTable *symtab, Addr base, Addr offset,
191 Addr addr_mask)
192 {
193 // nothing to do here
194 return false;
195 }