1 /* $NetBSD: load.cpp,v 1.14 2008/03/08 02:17:48 rafal Exp $ */
4 * Copyright (c) 2001 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 #include <exec_coff.h>
34 #undef DPRINTF // trash coff_machdep.h 's define.
42 Loader::Loader(Console
*&cons
, MemoryManager
*&mem
)
43 : _mem(mem
), _cons(cons
)
50 Loader::objectFormat(File
&file
)
56 file
.read(reinterpret_cast<void *>(&header
), sizeof(header
), 0);
58 if (header
.elf
.e_ident
[EI_MAG0
] == ELFMAG0
&&
59 header
.elf
.e_ident
[EI_MAG1
] == ELFMAG1
&&
60 header
.elf
.e_ident
[EI_MAG2
] == ELFMAG2
&&
61 header
.elf
.e_ident
[EI_MAG3
] == ELFMAG3
)
64 if (!COFF_BADMAG(&header
.coff
.f
))
68 return LOADER_UNKNOWN
;
72 Loader::loadExtData(void)
77 sz
= _file
->realsize();
78 kv
= ROUND(_kernend
, static_cast <vsize_t
>(KERNEL_PAGE_SIZE
));
80 DPRINTF((TEXT("[file system image]\n")));
81 _load_segment(kv
, sz
, 0, sz
);
83 return _load_success();
94 Loader::tagDump(int n
)
97 struct PageTag
*p
, *op
;
100 DPRINTF((TEXT("page tag start physical address: 0x%08x\n"),
102 p
= reinterpret_cast <struct PageTag
*>(_page_tag_start
);
104 if (i
< n
|| p
->src
== ~0)
105 DPRINTF((TEXT("[%d] next 0x%08x src 0x%08x dst 0x%08x sz 0x%x\n"),
106 i
, p
->next
, p
->src
, p
->dst
, p
->sz
));
108 DPRINTF((TEXT("[...]\n")));
111 } while ((p
= reinterpret_cast <struct PageTag
*>(p
->next
)) != ~0);
113 DPRINTF((TEXT("[%d(last)] next 0x%08x src 0x%08x dst 0x%08x sz 0x%x\n"),
114 i
- 1, op
->next
, op
->src
, op
->dst
, op
->sz
));
115 #endif // PAGE_LINK_DUMP
119 Loader::tagStart(void)
121 return _page_tag_start
;
125 Loader::_load_segment_start(void)
131 _nload_link
= _n0clr_link
= 0;
132 _tpsz
= _mem
->getTaggedPageSize();
135 if (!_mem
->getTaggedPage(v
, p
, &_pvec_clr
, _pvec_clr_paddr
))
137 #ifdef PAGE_LINK_DUMP
138 _page_tag_start
= (uint32_t)_pvec_clr
;
140 _page_tag_start
= _pvec_clr_paddr
;
142 _pvec_prev
= _pvec_clr
++;
143 _pvec_clr_paddr
+= sizeof(struct PageTag
);
147 Loader::_load_segment_end(void)
149 _opvec_prev
->next
= ~0; // terminate
150 DPRINTF((TEXT("load link %d, zero clear link %d\n"),
151 _nload_link
, _n0clr_link
));
155 Loader::_load_segment(vaddr_t kv
, vsize_t memsz
, off_t fileofs
, size_t filesz
)
158 vaddr_t kv_start
= kv
;
160 DPRINTF((TEXT("\t->load 0x%08x+0x%08x=0x%08x ofs=0x%08x+0x%x\n"),
161 kv
, memsz
, kv
+ memsz
, fileofs
, filesz
));
162 _kernend
= kv
+ memsz
;
166 for (j
= 0; j
< n
; j
++) {
167 _opvec_prev
= _pvec_prev
;
168 _pvec_prev
= _load_page(kv
, fileofs
,
174 size_t rest
= filesz
% _tpsz
;
176 _opvec_prev
= _pvec_prev
;
177 _pvec_prev
= _load_page(kv
, fileofs
, rest
, _pvec_prev
);
183 if (filesz
< memsz
) {
184 _pvec_prev
->src
= ~0;
185 _pvec_prev
->dst
= kv_start
+ filesz
;
186 _pvec_prev
->sz
= memsz
- filesz
;
187 #ifdef PAGE_LINK_DUMP
188 _pvec_prev
->next
= (uint32_t)_pvec_clr
;
190 _pvec_prev
->next
= ptokv(_pvec_clr_paddr
);
192 DPRINTF((TEXT("\t->zero 0x%08x+0x%08x=0x%08x\n"),
193 _pvec_prev
->dst
, _pvec_prev
->sz
,
194 _pvec_prev
->dst
+ _pvec_prev
->sz
));
195 _opvec_prev
= _pvec_prev
;
196 _pvec_prev
= _pvec_clr
++;
197 _pvec_clr_paddr
+= sizeof(struct PageTag
);
203 Loader::_load_memory(vaddr_t kv
, vsize_t memsz
, void *data
)
205 struct PageTag
*pvec
;
206 paddr_t p
, pvec_paddr
;
211 DPRINTF((TEXT("\t->load 0x%08x+0x%08x=0x%08x\n"),
212 kv
, memsz
, kv
+ memsz
));
217 _opvec_prev
= _pvec_prev
;
218 if (!_mem
->getTaggedPage(v
, p
, &pvec
, pvec_paddr
))
221 vsize_t tocopy
= (remsz
< _tpsz
) ? remsz
: _tpsz
;
222 memcpy((void *)v
, data
, tocopy
);
223 _pvec_prev
->src
= ptokv(p
);
224 _pvec_prev
->dst
= dst
;
225 _pvec_prev
->sz
= tocopy
;
226 #ifdef PAGE_LINK_DUMP
227 _pvec_prev
->next
= (uint32_t)pvec
;
229 _pvec_prev
->next
= ptokv(pvec_paddr
);
231 data
= (char *)data
+ tocopy
;
239 _kernend
= kv
+ memsz
;
243 Loader::_load_page(vaddr_t kv
, off_t ofs
, size_t sz
, struct PageTag
*prev
)
245 struct PageTag
*pvec
;
246 paddr_t p
, pvec_paddr
;
249 if (!_mem
->getTaggedPage(v
, p
, &pvec
, pvec_paddr
))
251 _file
->read((void *)v
, sz
, ofs
);
252 prev
->src
= ptokv(p
);
255 #ifdef PAGE_LINK_DUMP
256 prev
->next
= (uint32_t)pvec
;
258 prev
->next
= ptokv(pvec_paddr
);