1 1.15 martin /* $NetBSD: load.cpp,v 1.15 2008/04/28 20:23:20 martin Exp $ */ 2 1.1 uch 3 1.1 uch /*- 4 1.1 uch * Copyright (c) 2001 The NetBSD Foundation, Inc. 5 1.1 uch * All rights reserved. 6 1.1 uch * 7 1.1 uch * This code is derived from software contributed to The NetBSD Foundation 8 1.1 uch * by UCHIYAMA Yasushi. 9 1.1 uch * 10 1.1 uch * Redistribution and use in source and binary forms, with or without 11 1.1 uch * modification, are permitted provided that the following conditions 12 1.1 uch * are met: 13 1.1 uch * 1. Redistributions of source code must retain the above copyright 14 1.1 uch * notice, this list of conditions and the following disclaimer. 15 1.1 uch * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 uch * notice, this list of conditions and the following disclaimer in the 17 1.1 uch * documentation and/or other materials provided with the distribution. 18 1.1 uch * 19 1.1 uch * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 uch * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 uch * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 uch * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 uch * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 uch * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 uch * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 uch * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 uch * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 uch * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 uch * POSSIBILITY OF SUCH DAMAGE. 30 1.1 uch */ 31 1.1 uch 32 1.1 uch #include <load.h> 33 1.1 uch #include <exec_coff.h> 34 1.1 uch #undef DPRINTF // trash coff_machdep.h 's define. 35 1.1 uch 36 1.1 uch #include <console.h> 37 1.1 uch #include <memory.h> 38 1.1 uch #include <file.h> 39 1.1 uch 40 1.1 uch #include <exec_elf.h> 41 1.1 uch 42 1.1 uch Loader::Loader(Console *&cons, MemoryManager *&mem) 43 1.1 uch : _mem(mem), _cons(cons) 44 1.1 uch { 45 1.1 uch _file = 0; 46 1.1 uch _page_tag_start = 0; 47 1.1 uch } 48 1.1 uch 49 1.1 uch LoaderOps 50 1.1 uch Loader::objectFormat(File &file) 51 1.1 uch { 52 1.1 uch union { 53 1.1 uch Elf_Ehdr elf; 54 1.1 uch coff_exechdr coff; 55 1.1 uch } header; 56 1.1 uch file.read(reinterpret_cast<void *>(&header), sizeof(header), 0); 57 1.1 uch 58 1.1 uch if (header.elf.e_ident[EI_MAG0] == ELFMAG0 && 59 1.1 uch header.elf.e_ident[EI_MAG1] == ELFMAG1 && 60 1.1 uch header.elf.e_ident[EI_MAG2] == ELFMAG2 && 61 1.1 uch header.elf.e_ident[EI_MAG3] == ELFMAG3) 62 1.1 uch return LOADER_ELF; 63 1.1 uch #ifdef COFF_BADMAG 64 1.1 uch if (!COFF_BADMAG(&header.coff.f)) 65 1.1 uch return LOADER_COFF; 66 1.1 uch #endif // COFF_BADMAG 67 1.1 uch 68 1.1 uch return LOADER_UNKNOWN; 69 1.1 uch } 70 1.1 uch 71 1.5 uch BOOL 72 1.1 uch Loader::loadExtData(void) 73 1.1 uch { 74 1.1 uch size_t sz; 75 1.1 uch vaddr_t kv; 76 1.1 uch 77 1.6 uwe sz = _file->realsize(); 78 1.1 uch kv = ROUND(_kernend, static_cast <vsize_t>(KERNEL_PAGE_SIZE)); 79 1.1 uch 80 1.11 uwe DPRINTF((TEXT("[file system image]\n"))); 81 1.1 uch _load_segment(kv, sz, 0, sz); 82 1.5 uch 83 1.5 uch return _load_success(); 84 1.1 uch } 85 1.1 uch 86 1.1 uch void 87 1.1 uch Loader::loadEnd(void) 88 1.7 uch { 89 1.1 uch /* tag chain end */ 90 1.1 uch _load_segment_end(); 91 1.1 uch } 92 1.1 uch 93 1.1 uch void 94 1.1 uch Loader::tagDump(int n) 95 1.1 uch { 96 1.1 uch #ifdef PAGE_LINK_DUMP 97 1.1 uch struct PageTag *p, *op; 98 1.1 uch int i = 0; 99 1.7 uch 100 1.1 uch DPRINTF((TEXT("page tag start physical address: 0x%08x\n"), 101 1.4 uch _page_tag_start)); 102 1.1 uch p = reinterpret_cast <struct PageTag *>(_page_tag_start); 103 1.1 uch do { 104 1.1 uch if (i < n || p->src == ~0) 105 1.1 uch DPRINTF((TEXT("[%d] next 0x%08x src 0x%08x dst 0x%08x sz 0x%x\n"), 106 1.4 uch i, p->next, p->src, p->dst, p->sz)); 107 1.1 uch else if (i == n) 108 1.1 uch DPRINTF((TEXT("[...]\n"))); 109 1.1 uch op = p; 110 1.1 uch i++; 111 1.1 uch } while ((p = reinterpret_cast <struct PageTag *>(p->next)) != ~0); 112 1.7 uch 113 1.1 uch DPRINTF((TEXT("[%d(last)] next 0x%08x src 0x%08x dst 0x%08x sz 0x%x\n"), 114 1.4 uch i - 1, op->next, op->src, op->dst, op->sz)); 115 1.1 uch #endif // PAGE_LINK_DUMP 116 1.1 uch } 117 1.1 uch 118 1.1 uch paddr_t 119 1.1 uch Loader::tagStart(void) 120 1.7 uch { 121 1.1 uch return _page_tag_start; 122 1.1 uch } 123 1.1 uch 124 1.1 uch void 125 1.1 uch Loader::_load_segment_start(void) 126 1.1 uch { 127 1.1 uch vaddr_t v; 128 1.1 uch paddr_t p; 129 1.1 uch 130 1.5 uch _error = FALSE; 131 1.1 uch _nload_link = _n0clr_link = 0; 132 1.1 uch _tpsz = _mem->getTaggedPageSize(); 133 1.1 uch 134 1.1 uch // start of chain. 135 1.5 uch if (!_mem->getTaggedPage(v, p, &_pvec_clr, _pvec_clr_paddr)) 136 1.5 uch _error = TRUE; 137 1.1 uch #ifdef PAGE_LINK_DUMP 138 1.10 uwe _page_tag_start = (uint32_t)_pvec_clr; 139 1.1 uch #else 140 1.1 uch _page_tag_start = _pvec_clr_paddr; 141 1.1 uch #endif 142 1.1 uch _pvec_prev = _pvec_clr++; 143 1.1 uch _pvec_clr_paddr += sizeof(struct PageTag); 144 1.1 uch } 145 1.1 uch 146 1.1 uch void 147 1.1 uch Loader::_load_segment_end(void) 148 1.1 uch { 149 1.1 uch _opvec_prev->next = ~0; // terminate 150 1.13 uwe DPRINTF((TEXT("load link %d, zero clear link %d\n"), 151 1.4 uch _nload_link, _n0clr_link)); 152 1.1 uch } 153 1.1 uch 154 1.1 uch void 155 1.1 uch Loader::_load_segment(vaddr_t kv, vsize_t memsz, off_t fileofs, size_t filesz) 156 1.1 uch { 157 1.1 uch int j, n; 158 1.1 uch vaddr_t kv_start = kv; 159 1.1 uch 160 1.1 uch DPRINTF((TEXT("\t->load 0x%08x+0x%08x=0x%08x ofs=0x%08x+0x%x\n"), 161 1.4 uch kv, memsz, kv + memsz, fileofs, filesz)); 162 1.3 uch _kernend = kv + memsz; 163 1.3 uch 164 1.1 uch if (filesz) { 165 1.1 uch n = filesz / _tpsz; 166 1.1 uch for (j = 0; j < n; j++) { 167 1.1 uch _opvec_prev = _pvec_prev; 168 1.1 uch _pvec_prev = _load_page(kv, fileofs, 169 1.4 uch _tpsz, _pvec_prev); 170 1.1 uch kv += _tpsz; 171 1.1 uch fileofs += _tpsz; 172 1.1 uch ++_nload_link; 173 1.1 uch } 174 1.1 uch size_t rest = filesz % _tpsz; 175 1.1 uch if (rest) { 176 1.1 uch _opvec_prev = _pvec_prev; 177 1.1 uch _pvec_prev = _load_page(kv, fileofs, rest, _pvec_prev); 178 1.1 uch ++_nload_link; 179 1.1 uch } 180 1.1 uch } 181 1.1 uch 182 1.1 uch // zero clear tag 183 1.1 uch if (filesz < memsz) { 184 1.1 uch _pvec_prev->src = ~0; 185 1.1 uch _pvec_prev->dst = kv_start + filesz; 186 1.1 uch _pvec_prev->sz = memsz - filesz; 187 1.1 uch #ifdef PAGE_LINK_DUMP 188 1.10 uwe _pvec_prev->next = (uint32_t)_pvec_clr; 189 1.1 uch #else 190 1.1 uch _pvec_prev->next = ptokv(_pvec_clr_paddr); 191 1.1 uch #endif 192 1.9 uwe DPRINTF((TEXT("\t->zero 0x%08x+0x%08x=0x%08x\n"), 193 1.4 uch _pvec_prev->dst, _pvec_prev->sz, 194 1.4 uch _pvec_prev->dst + _pvec_prev->sz)); 195 1.1 uch _opvec_prev = _pvec_prev; 196 1.1 uch _pvec_prev = _pvec_clr++; 197 1.1 uch _pvec_clr_paddr += sizeof(struct PageTag); 198 1.1 uch ++_n0clr_link; 199 1.1 uch } 200 1.2 toshii } 201 1.2 toshii 202 1.2 toshii void 203 1.2 toshii Loader::_load_memory(vaddr_t kv, vsize_t memsz, void *data) 204 1.2 toshii { 205 1.2 toshii struct PageTag *pvec; 206 1.2 toshii paddr_t p, pvec_paddr; 207 1.10 uwe vaddr_t v; 208 1.12 uwe vaddr_t dst; 209 1.12 uwe vsize_t remsz; 210 1.2 toshii 211 1.2 toshii DPRINTF((TEXT("\t->load 0x%08x+0x%08x=0x%08x\n"), 212 1.4 uch kv, memsz, kv + memsz)); 213 1.2 toshii 214 1.12 uwe dst = kv; 215 1.12 uwe remsz = memsz; 216 1.12 uwe while (remsz > 0) { 217 1.12 uwe _opvec_prev = _pvec_prev; 218 1.12 uwe if (!_mem->getTaggedPage(v, p, &pvec, pvec_paddr)) 219 1.12 uwe _error = TRUE; 220 1.12 uwe 221 1.12 uwe vsize_t tocopy = (remsz < _tpsz) ? remsz : _tpsz; 222 1.12 uwe memcpy((void *)v, data, tocopy); 223 1.12 uwe _pvec_prev->src = ptokv(p); 224 1.12 uwe _pvec_prev->dst = dst; 225 1.12 uwe _pvec_prev->sz = tocopy; 226 1.2 toshii #ifdef PAGE_LINK_DUMP 227 1.12 uwe _pvec_prev->next = (uint32_t)pvec; 228 1.2 toshii #else 229 1.12 uwe _pvec_prev->next = ptokv(pvec_paddr); 230 1.2 toshii #endif 231 1.12 uwe data = (char *)data + tocopy; 232 1.12 uwe dst += tocopy; 233 1.12 uwe remsz -= tocopy; 234 1.12 uwe 235 1.12 uwe _pvec_prev = pvec; 236 1.14 rafal ++_nload_link; 237 1.12 uwe } 238 1.2 toshii 239 1.2 toshii _kernend = kv + memsz; 240 1.1 uch } 241 1.1 uch 242 1.1 uch struct PageTag * 243 1.1 uch Loader::_load_page(vaddr_t kv, off_t ofs, size_t sz, struct PageTag *prev) 244 1.1 uch { 245 1.1 uch struct PageTag *pvec; 246 1.1 uch paddr_t p, pvec_paddr; 247 1.1 uch vaddr_t v; 248 1.1 uch 249 1.5 uch if (!_mem->getTaggedPage(v, p, &pvec, pvec_paddr)) 250 1.5 uch _error = TRUE; 251 1.1 uch _file->read((void *)v, sz, ofs); 252 1.1 uch prev->src = ptokv(p); 253 1.1 uch prev->dst = kv; 254 1.1 uch prev->sz = sz; 255 1.1 uch #ifdef PAGE_LINK_DUMP 256 1.10 uwe prev->next = (uint32_t)pvec; 257 1.1 uch #else 258 1.1 uch prev->next = ptokv(pvec_paddr); 259 1.1 uch #endif 260 1.1 uch 261 1.1 uch return pvec; 262 1.1 uch } 263