1 /* $NetBSD: load.cpp,v 1.1 2001/02/09 18:34:44 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 if (filesz) { 166 n = filesz / _tpsz; 167 for (j = 0; j < n; j++) { 168 _opvec_prev = _pvec_prev; 169 _pvec_prev = _load_page(kv, fileofs, 170 _tpsz, _pvec_prev); 171 kv += _tpsz; 172 fileofs += _tpsz; 173 ++_nload_link; 174 } 175 size_t rest = filesz % _tpsz; 176 if (rest) { 177 _opvec_prev = _pvec_prev; 178 _pvec_prev = _load_page(kv, fileofs, rest, _pvec_prev); 179 ++_nload_link; 180 } 181 } 182 183 // zero clear tag 184 if (filesz < memsz) { 185 _pvec_prev->src = ~0; 186 _pvec_prev->dst = kv_start + filesz; 187 _pvec_prev->sz = memsz - filesz; 188 #ifdef PAGE_LINK_DUMP 189 _pvec_prev->next =(u_int32_t)_pvec_clr; 190 #else 191 _pvec_prev->next = ptokv(_pvec_clr_paddr); 192 #endif 193 DPRINTF((TEXT("[zero clear] ->0x%08x+0x%08x=0x%08x\n"), 194 _pvec_prev->dst, _pvec_prev->sz, 195 _pvec_prev->dst + _pvec_prev->sz)); 196 _opvec_prev = _pvec_prev; 197 _pvec_prev = _pvec_clr++; 198 _pvec_clr_paddr += sizeof(struct PageTag); 199 ++_n0clr_link; 200 } 201 _kernend = kv + memsz; 202 } 203 204 struct PageTag * 205 Loader::_load_page(vaddr_t kv, off_t ofs, size_t sz, struct PageTag *prev) 206 { 207 struct PageTag *pvec; 208 paddr_t p, pvec_paddr; 209 vaddr_t v; 210 211 _mem->getTaggedPage(v, p, &pvec, pvec_paddr); 212 _file->read((void *)v, sz, ofs); 213 prev->src = ptokv(p); 214 prev->dst = kv; 215 prev->sz = sz; 216 #ifdef PAGE_LINK_DUMP 217 prev->next =(u_int32_t)pvec; 218 #else 219 prev->next = ptokv(pvec_paddr); 220 #endif 221 222 return pvec; 223 } 224