1/* $NetBSD: loadfile_ecoff.c,v 1.11 2007/12/29 17:54:42 tsutsui Exp $ */
2
3/*-
4 * Copyright (c) 1997 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center and by Christos Zoulas.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#ifdef _STANDALONE
34#include <lib/libsa/stand.h>
35#include <lib/libkern/libkern.h>
36#else
37#include <stdio.h>
38#include <string.h>
39#include <errno.h>
40#include <stdlib.h>
41#include <unistd.h>
42#include <fcntl.h>
43#include <err.h>
44#endif
45
46#include <sys/param.h>
47#include <sys/exec.h>
48
49#include "loadfile.h"
50
51#ifdef BOOT_ECOFF
52
53int
54loadfile_coff(int fd, struct ecoff_exechdr *coff, u_long *marks, int flags)
55{
56	paddr_t offset = marks[MARK_START];
57	paddr_t minp = ~0, maxp = 0, pos;
58	ssize_t nr;
59
60	/* some ports dont use the offset */
61	offset = offset;
62
63	/* Read in text. */
64	if (lseek(fd, ECOFF_TXTOFF(coff), SEEK_SET) == -1)  {
65		WARN(("lseek text"));
66		return 1;
67	}
68
69	if (coff->a.tsize != 0) {
70		if (flags & LOAD_TEXT) {
71			PROGRESS(("%lu", coff->a.tsize));
72			nr = READ(fd, coff->a.text_start, coff->a.tsize);
73			if (nr == -1) {
74				return 1;
75			}
76			if (nr != coff->a.tsize) {
77				errno = EIO;
78				return 1;
79			}
80		}
81		else {
82			if (lseek(fd, coff->a.tsize, SEEK_CUR) == -1) {
83				WARN(("read text"));
84				return 1;
85			}
86		}
87		if (flags & (COUNT_TEXT|LOAD_TEXT)) {
88			pos = coff->a.text_start;
89			if (minp > pos)
90				minp = pos;
91			pos += coff->a.tsize;
92			if (maxp < pos)
93				maxp = pos;
94		}
95	}
96
97	/* Read in data. */
98	if (coff->a.dsize != 0) {
99		if (flags & LOAD_DATA) {
100			PROGRESS(("+%lu", coff->a.dsize));
101			nr = READ(fd, coff->a.data_start, coff->a.dsize);
102			if (nr == -1) {
103				WARN(("read data"));
104				return 1;
105			}
106			if (nr != coff->a.dsize) {
107				errno = EIO;
108				WARN(("read data"));
109				return 1;
110			}
111		}
112		if (flags & (COUNT_DATA|LOAD_DATA)) {
113			pos = coff->a.data_start;
114			if (minp > pos)
115				minp = pos;
116			pos += coff->a.dsize;
117			if (maxp < pos)
118				maxp = pos;
119		}
120	}
121
122	/* Zero out bss. */
123	if (coff->a.bsize != 0) {
124		if (flags & LOAD_BSS) {
125			PROGRESS(("+%lu", coff->a.bsize));
126			BZERO(coff->a.bss_start, coff->a.bsize);
127		}
128		if (flags & (COUNT_BSS|LOAD_BSS)) {
129			pos = coff->a.bss_start;
130			if (minp > pos)
131				minp = pos;
132			pos = coff->a.bsize;
133			if (maxp < pos)
134				maxp = pos;
135		}
136	}
137
138	marks[MARK_START] = LOADADDR(minp);
139	marks[MARK_ENTRY] = LOADADDR(coff->a.entry);
140	marks[MARK_NSYM] = 1;	/* XXX: Kernel needs >= 0 */
141	marks[MARK_SYM] = LOADADDR(maxp);
142	marks[MARK_END] = LOADADDR(maxp);
143	marks[MARK_DATA] = LOADADDR(coff->a.data_start);
144	return 0;
145}
146
147#endif /* BOOT_ECOFF */
148