1 /* $NetBSD: load.cpp,v 1.4 2001/05/08 18:51:22 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 void 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 91 void 92 Loader::loadEnd(void) 93 { 94 /* tag chain end */ 95 _load_segment_end(); 96 } 97 98 void 99 Loader::tagDump(int n) 100 { 101 #ifdef PAGE_LINK_DUMP 102 struct PageTag *p, *op; 103 int i = 0; 104 105 DPRINTF((TEXT("page tag start physical address: 0x%08x\n"), 106 _page_tag_start)); 107 p = reinterpret_cast <struct PageTag *>(_page_tag_start); 108 do { 109 if (i < n || p->src == ~0) 110 DPRINTF((TEXT("[%d] next 0x%08x src 0x%08x dst 0x%08x sz 0x%x\n"), 111 i, p->next, p->src, p->dst, p->sz)); 112 else if (i == n) 113 DPRINTF((TEXT("[...]\n"))); 114 op = p; 115 i++; 116 } while ((p = reinterpret_cast <struct PageTag *>(p->next)) != ~0); 117 118 DPRINTF((TEXT("[%d(last)] next 0x%08x src 0x%08x dst 0x%08x sz 0x%x\n"), 119 i - 1, op->next, op->src, op->dst, op->sz)); 120 #endif // PAGE_LINK_DUMP 121 } 122 123 paddr_t 124 Loader::tagStart(void) 125 { 126 return _page_tag_start; 127 } 128 129 void 130 Loader::_load_segment_start(void) 131 { 132 vaddr_t v; 133 paddr_t p; 134 135 _nload_link = _n0clr_link = 0; 136 _tpsz = _mem->getTaggedPageSize(); 137 138 // start of chain. 139 _mem->getTaggedPage(v, p, &_pvec_clr, _pvec_clr_paddr); 140 #ifdef PAGE_LINK_DUMP 141 _page_tag_start =(u_int32_t)_pvec_clr; 142 #else 143 _page_tag_start = _pvec_clr_paddr; 144 #endif 145 _pvec_prev = _pvec_clr++; 146 _pvec_clr_paddr += sizeof(struct PageTag); 147 } 148 149 void 150 Loader::_load_segment_end(void) 151 { 152 _opvec_prev->next = ~0; // terminate 153 DPRINTF((TEXT("load link %d zero clear link %d.\n"), 154 _nload_link, _n0clr_link)); 155 } 156 157 void 158 Loader::_load_segment(vaddr_t kv, vsize_t memsz, off_t fileofs, size_t filesz) 159 { 160 int j, n; 161 vaddr_t kv_start = kv; 162 163 DPRINTF((TEXT("\t->load 0x%08x+0x%08x=0x%08x ofs=0x%08x+0x%x\n"), 164 kv, memsz, kv + memsz, fileofs, filesz)); 165 _kernend = kv + memsz; 166 167 if (filesz) { 168 n = filesz / _tpsz; 169 for (j = 0; j < n; j++) { 170 _opvec_prev = _pvec_prev; 171 _pvec_prev = _load_page(kv, fileofs, 172 _tpsz, _pvec_prev); 173 kv += _tpsz; 174 fileofs += _tpsz; 175 ++_nload_link; 176 } 177 size_t rest = filesz % _tpsz; 178 if (rest) { 179 _opvec_prev = _pvec_prev; 180 _pvec_prev = _load_page(kv, fileofs, rest, _pvec_prev); 181 ++_nload_link; 182 } 183 } 184 185 // zero clear tag 186 if (filesz < memsz) { 187 _pvec_prev->src = ~0; 188 _pvec_prev->dst = kv_start + filesz; 189 _pvec_prev->sz = memsz - filesz; 190 #ifdef PAGE_LINK_DUMP 191 _pvec_prev->next =(u_int32_t)_pvec_clr; 192 #else 193 _pvec_prev->next = ptokv(_pvec_clr_paddr); 194 #endif 195 DPRINTF((TEXT("[zero clear] ->0x%08x+0x%08x=0x%08x\n"), 196 _pvec_prev->dst, _pvec_prev->sz, 197 _pvec_prev->dst + _pvec_prev->sz)); 198 _opvec_prev = _pvec_prev; 199 _pvec_prev = _pvec_clr++; 200 _pvec_clr_paddr += sizeof(struct PageTag); 201 ++_n0clr_link; 202 } 203 } 204 205 void 206 Loader::_load_memory(vaddr_t kv, vsize_t memsz, void *data) 207 { 208 struct PageTag *pvec; 209 vaddr_t kv_start = kv, v; 210 paddr_t p, pvec_paddr; 211 212 DPRINTF((TEXT("\t->load 0x%08x+0x%08x=0x%08x\n"), 213 kv, memsz, kv + memsz)); 214 if (memsz > _tpsz) { 215 /* XXX failure */ 216 return; 217 } 218 219 _opvec_prev = _pvec_prev; 220 _mem->getTaggedPage(v, p, &pvec, pvec_paddr); 221 memcpy((void *)v, data, memsz); 222 _pvec_prev->src = ptokv(p); 223 _pvec_prev->dst = kv; 224 _pvec_prev->sz = memsz; 225 #ifdef PAGE_LINK_DUMP 226 _pvec_prev->next =(u_int32_t)pvec; 227 #else 228 _pvec_prev->next = ptokv(pvec_paddr); 229 #endif 230 _pvec_prev = pvec; 231 232 _kernend = kv + memsz; 233 ++_nload_link; 234 } 235 236 struct PageTag * 237 Loader::_load_page(vaddr_t kv, off_t ofs, size_t sz, struct PageTag *prev) 238 { 239 struct PageTag *pvec; 240 paddr_t p, pvec_paddr; 241 vaddr_t v; 242 243 _mem->getTaggedPage(v, p, &pvec, pvec_paddr); 244 _file->read((void *)v, sz, ofs); 245 prev->src = ptokv(p); 246 prev->dst = kv; 247 prev->sz = sz; 248 #ifdef PAGE_LINK_DUMP 249 prev->next =(u_int32_t)pvec; 250 #else 251 prev->next = ptokv(pvec_paddr); 252 #endif 253 254 return pvec; 255 } 256