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