1 /*        $NetBSD: bootxx.c,v 1.6 2020/06/07 03:00:53 tsutsui Exp $   */
2 
3 /*-
4  * Copyright (c) 2004, 2005 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  *
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.
30  */
31 
32 #ifdef _STANDALONE
33 #include <lib/libsa/stand.h>
34 #include <lib/libkern/libkern.h>
35 #endif
36 
37 #include <sys/types.h>
38 #include <sys/param.h>
39 #include "bootxx.h"
40 
41 #include <sys/exec_ecoff.h>
42 #include <sys/exec_elf.h>
43 
44 #include <machine/sector.h>
45 #include <machine/sbd.h>
46 
47 #include "common.h"
48 
49 #define   IS_TEXT(p)          (p.p_flags & PF_X)
50 #define   IS_DATA(p)          ((p.p_flags & PF_X) == 0)
51 #define   IS_BSS(p) (p.p_filesz < p.p_memsz)
52 
53 #define   FILHSZ    (sizeof(struct ecoff_filehdr))
54 #define   SCNHSZ    (sizeof(struct ecoff_scnhdr))
55 #define   N_TXTOFF(f, a)                                                                  \
56           ((a)->vstamp < 23 ?                                                   \
57           ((FILHSZ +(f)->f_opthdr +(f)->f_nscns * SCNHSZ + 7) & ~7) : \
58           ((FILHSZ +(f)->f_opthdr +(f)->f_nscns * SCNHSZ + 15) & ~15))
59 
60 int main(void);
61 int loader(const char *, uint32_t *);
62 int load_elf(uint8_t *, uint32_t *);
63 int load_coff(uint8_t *, uint32_t *);
64 int dk_read(int, int, void *);
65 
66 const char *errmsg[] = {
67           [BERR_PDINFO]                 = "No PDINFO",
68           [BERR_RDVTOC]                 = "VTOC read error",
69           [BERR_VTOC]                   = "VTOC bad magic",
70           [BERR_NOBFS]                  = "No BFS partition",
71           [BERR_RDINODE]                = "I-node read error",
72           [BERR_NOROOT]                 = "No root",
73           [BERR_RDDIRENT]               = "Dirent read error",
74           [BERR_NOFILE]                 = "No such a file",
75           [BERR_RDFILE]                 = "File read error",
76           [BERR_FILEMAGIC]    = "Bad file magic",
77           [BERR_AOUTHDR]                = "Not a OMAGIC",
78           [BERR_ELFHDR]                 = "Not a ELF",
79           [BERR_TARHDR]                 = "Read tar file",
80           [BERR_TARMAGIC]               = "Bad tar magic",
81 };
82 
83 const char *boottab[] = {
84           "boot",             /* NetBSD (bfs,ustarfs) */
85           "iopboot",          /* EWS-UX (bfs) */
86           0                   /* terminate */
87 };
88 
89 int __dk_unit, __dk_type, __spb;
90 bool (*fd_position)(uint32_t, uint32_t *, int *);
91 
92 int
main(void)93 main(void)
94 {
95           char msg[] = "[+++] NetBSD/ews4800mips >> ";
96           const char *p;
97           const char **boot;
98           uint32_t entry;
99           int err;
100 
101 #ifdef _STANDALONE
102           int i, fd_format;
103 
104           boot_device(&__dk_type, &__dk_unit, &fd_format);
105           msg[1] = __dk_type + '0';
106           msg[2] = __dk_unit + '0';
107           msg[3] = FS_SIGNATURE;
108           for (i = 0; msg[i] != 0; i++)
109                     ROM_PUTC(32 + i * 12, 536, msg[i]);
110 
111           if (__dk_type == NVSRAM_BOOTDEV_FLOPPYDISK) {
112                     fd_position = blk_to_2d_position;
113                     if (fd_format == FD_FORMAT_2D) {
114                               fd_position = blk_to_2d_position;
115                               __spb = 2;                    /* 256bytes/sector */
116                     } else {
117                               fd_position = blk_to_2hd_position;
118                               __dk_unit |= 0x1000000;                 /* | 2HD flag */
119                               __spb = 1;
120                     }
121           }
122 #else
123           printf("%s\n", msg);
124           sector_init("/dev/rsd1p", DEV_BSIZE);
125           sector_read(SDBOOT_PDINFOADDR, PDINFO_SECTOR);
126 #endif
127 
128           for (boot = boottab; *boot; boot++) {
129                     if ((err = loader(*boot, &entry)) == 0) {
130 #ifdef _STANDALONE
131                               ROM_PUTC(0, 0, '\n');
132                               ROM_PUTC(0, 0, '\r');
133                               return entry;
134 #else
135                               printf("entry=%p\n", (void *)entry);
136                               sector_fini();
137                               return 0;
138 #endif
139                     }
140                     p = errmsg[err];
141 #ifdef _STANDALONE
142                     for (i = 0; p[i] != 0; i++)
143                               ROM_PUTC(600 + i * 12, 536, p[i]);
144 #else
145                     DPRINTF("***ERROR *** %s\n", p);
146 #endif
147           }
148 
149 #ifdef _STANDALONE
150           while (/*CONSTCOND*/1)
151                     ;
152           /* NOTREACHED */
153 #else
154           sector_fini();
155 #endif
156           return 0;
157 }
158 
159 int
loader(const char * fname,uint32_t * entry)160 loader(const char *fname, uint32_t *entry)
161 {
162           int err;
163           uint16_t mag;
164           size_t sz;
165 #ifdef _STANDALONE
166           int i;
167 
168           for (i = 0; fname[i] != 0; i++)
169                     ROM_PUTC(380 + i * 12, 536, fname[i]);
170 #else
171           printf("%s\n", fname);
172 #endif
173 
174           if ((err = fileread(fname, &sz)) != 0)
175                     return err;
176 
177           DPRINTF("%s found. %d bytes.\n", fname, sz);
178 
179           mag = *(uint16_t *)SDBOOT_SCRATCHADDR;
180           if (mag == 0x7f45)
181                     return load_elf((uint8_t *)SDBOOT_SCRATCHADDR, entry);
182           else if (mag == ECOFF_MAGIC_MIPSEB)
183                     return load_coff((uint8_t *)SDBOOT_SCRATCHADDR, entry);
184 
185           return BERR_FILEMAGIC;
186 }
187 
188 int
load_elf(uint8_t * buf,uint32_t * entry)189 load_elf(uint8_t *buf, uint32_t *entry)
190 {
191           Elf32_Ehdr *e = (void *)buf;
192           Elf32_Phdr *p;
193           int i;
194 
195           if (e->e_ident[EI_MAG2] != 'L' || e->e_ident[EI_MAG3] != 'F' ||
196               e->e_ident[EI_CLASS] != ELFCLASS32 ||
197               e->e_ident[EI_DATA] != ELFDATA2MSB ||
198               e->e_type != ET_EXEC ||
199               e->e_machine != EM_MIPS)
200                     return BERR_ELFHDR;
201 
202           BASSERT(e->e_phentsize == sizeof(Elf32_Phdr));
203           p = (void *)(buf + e->e_phoff);
204 #ifdef _STANDALONE
205           for (i = 0; i < e->e_phnum; i++) {
206                     if (p[i].p_type != PT_LOAD ||
207                         (p[i].p_flags & (PF_W|PF_R|PF_X)) == 0)
208                               continue;
209                     if (IS_TEXT(p[i]) || IS_DATA(p[i])) {
210                               memcpy((void *)p[i].p_vaddr,
211                                   buf + p[i].p_offset, p[i].p_filesz);
212                     }
213                     if (IS_BSS(p[i])) {
214                               memset((void *)(p[i].p_vaddr + p[i].p_filesz), 0,
215                                   p[i].p_memsz - p[i].p_filesz);
216                     }
217           }
218 #else
219           DPRINTF("ELF entry point 0x%08x\n", e->e_entry);
220           for (i = 0; i < e->e_phnum; i++) {
221                     if (p[i].p_type != PT_LOAD ||
222                         (p[i].p_flags & (PF_W|PF_R|PF_X)) == 0)
223                               continue;
224                     if (IS_TEXT(p[i]) || IS_DATA(p[i])) {
225                               DPRINTF("[text/data] 0x%08x 0x%x %dbyte.\n",
226                                   p[i].p_vaddr, p[i].p_offset, p[i].p_filesz);
227                     }
228                     if (IS_BSS(p[i])) {
229                               DPRINTF("[bss] 0x%08x %dbyte.\n",
230                                   p[i].p_vaddr + p[i].p_filesz,
231                                   p[i].p_memsz - p[i].p_filesz);
232                     }
233           }
234 #endif
235           *entry = e->e_entry;
236 
237           return 0;
238 }
239 
240 int
load_coff(uint8_t * p,uint32_t * entry)241 load_coff(uint8_t *p, uint32_t *entry)
242 {
243           struct ecoff_exechdr *eh = (void *)p;
244           struct ecoff_aouthdr *a = &eh->a;
245           struct ecoff_filehdr *f = &eh->f;
246 
247           if (a->magic != ECOFF_OMAGIC)
248                     return BERR_AOUTHDR;
249 
250           p += N_TXTOFF(f, a);
251           DPRINTF("file offset = 0x%x\n", N_TXTOFF(f, a));
252 #ifdef _STANDALONE
253           memcpy((void *)a->text_start, p, a->tsize);
254           memcpy((void *)a->data_start, p + a->tsize, a->dsize);
255 #else
256           DPRINTF("COFF entry point 0x%08lx\n", a->entry);
257           DPRINTF("[text] 0x%08lx %ld byte.\n", a->text_start, a->tsize);
258           DPRINTF("[data] 0x%08lx %ld byte.\n", a->data_start, a->dsize);
259 #endif
260 
261           *entry = a->entry;
262 
263           return 0;
264 }
265 
266 int
dk_read(int sector,int count,void * buf)267 dk_read(int sector, int count, void *buf)
268 {
269 #ifdef _STANDALONE
270           int cnt;
271           uint32_t pos;
272           uint8_t *p = buf;
273 
274           if (__dk_type == NVSRAM_BOOTDEV_HARDDISK) {       /* DISK */
275                     if ((ROM_DK_READ(__dk_unit, sector, count, p) & 0x7f) != 0)
276                               return 1;
277           } else {  /* FD */
278                     while (count > 0) {
279                               fd_position(sector, &pos, &cnt);
280                               if (cnt > count)
281                                         cnt = count;
282                               if ((ROM_FD_READ(__dk_unit, pos, cnt * __spb, p)
283                                   & 0x7f) != 0)
284                                         return 1;
285                               count -= cnt;
286                               sector += cnt;
287                               p += 512 * cnt;
288                     }
289           }
290 #else
291           sector_read_n(buf, sector, count);
292 #endif
293           return 0;
294 }
295