1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #include <sys/sysmacros.h>
27 #include <sys/types.h>
28 #include <sys/exechdr.h>
29 #include <sys/elf.h>
30 #include <sys/elf_notes.h>
31 #include <sys/bootconf.h>
32 #include <sys/reboot.h>
33 #include <sys/fcntl.h>
34 #include <sys/stat.h>
35 #include <sys/modctl.h>
36 #include <sys/link.h>
37 #include <sys/auxv.h>
38 #include <sys/salib.h>
39 #include <sys/bootvfs.h>
40 #include <sys/platnames.h>
41
42 #include "util.h"
43
44 union {
45 struct exec X;
46 Elf32_Ehdr Elfhdr;
47 Elf64_Ehdr Elfhdr64;
48 } ex;
49
50 #define x ex.X
51 #define elfhdr ex.Elfhdr
52 #define elfhdr64 ex.Elfhdr64
53
54 typedef int (*func_t)();
55
56 #define FAIL ((func_t)-1)
57 #define ALIGN(x, a) \
58 ((a) == 0 ? (uintptr_t)(x) : (((uintptr_t)(x) + (a) - 1) & ~((a) - 1)))
59
60 #define __BOOT_NAUXV_IMPL 22
61
62 int use_align = 0;
63 int npagesize = 0;
64 uint_t icache_flush = 0;
65 char *cpulist = NULL;
66 char *mmulist = NULL;
67 extern char *module_path; /* path for kernel modules */
68
69 /*
70 * This file gets compiled in LP64 (for sun4u) and ILP32 models.
71 * For LP64 compilation, the "client" file we load and run may be LP64 or ILP32,
72 * and during bringup, the LP64 clients may have ELF32 headers.
73 */
74 #ifdef _ELF64_SUPPORT
75 /*
76 * Bootstrap vector for ELF32 LP64 client
77 */
78 Elf32_Boot *elfbootvecELF32_64;
79 Elf64_Boot *elfbootvecELF64; /* ELF bootstrap vector for Elf64 LP64 */
80
81 #define OK ((func_t)0)
82
83 #define FAIL_READELF64 ((uint64_t)0)
84 #define FAIL_ILOAD64 ((Elf64_Addr)-1)
85 #endif /* _ELF64_SUPPORT */
86
87 /*
88 * And by an ILP32 client. The non-sun4u/LP64 booters use these.
89 * Also, the sun4u booter must create this for ILP32 clients.
90 */
91 Elf32_Boot *elfbootvec; /* ELF bootstrap vector normal ILP32 */
92
93 /*
94 * Read in a Unix executable file and return its entry point.
95 * Handle the various a.out formats correctly.
96 * "fd" is the standalone file descriptor to read from.
97 * Print informative little messages if "print" is on.
98 * Returns -1 for errors.
99 */
100
101 #ifdef DEBUG
102 static int debug = 1;
103 #else /* DEBUG */
104 static int debug = 0;
105 #endif /* DEBUG */
106
107 #define dprintf if (debug) printf
108
109 #ifdef _ELF64_SUPPORT
110 typedef struct {
111 uint_t a_type;
112 union {
113 uint64_t a_val;
114 uint64_t a_ptr;
115 void (*a_fcn)(); /* XXX - UNUSED? */
116 } a_un;
117 } auxv64_t;
118
119 #if defined(__sparcv9)
120 extern int client_isLP64;
121 #endif /* __sparcv9 */
122
123 static uint64_t read_elf64(int, int, Elf64_Ehdr *);
124 static Elf64_Addr iload64(char *, Elf64_Phdr *, Elf64_Phdr *, auxv64_t **);
125 #endif /* _ELF64_SUPPORT */
126
127 static func_t read_elf32(int, int, Elf32_Ehdr *);
128 static func_t iload32(char *, Elf32_Phdr *, Elf32_Phdr *, auxv32_t **);
129 static caddr_t segbrk(caddr_t *, size_t, size_t);
130 static int openpath(char *, char *, int);
131 static char *getmodpath(char *);
132 extern void setup_aux(void);
133
134 extern void *kmem_alloc(size_t, int);
135 extern void kmem_free(void *, size_t);
136 extern int cons_gets(char *, int);
137
138 extern void sync_instruction_memory(caddr_t v, size_t len);
139
140 extern int verbosemode;
141 extern int boothowto;
142 extern int pagesize;
143 extern char filename[];
144
145 /*
146 * repeat reads (forever) until size of request is satisfied
147 * (Thus, you don't want to use this cases where short reads are ok)
148 */
149 ssize_t
xread(int fd,char * p,size_t nbytes)150 xread(int fd, char *p, size_t nbytes)
151 {
152 size_t bytesread = 0;
153 int errorcount = 0;
154 ssize_t i;
155
156 while (bytesread < nbytes) {
157 i = read(fd, p, nbytes - bytesread);
158 if (i < 0) {
159 ++errorcount;
160 if (verbosemode)
161 printf("read error (0x%x times)\n", errorcount);
162 continue;
163 }
164 bytesread += i;
165 p += i;
166 }
167 return (bytesread);
168 }
169
170 func_t
readfile(int fd,int print)171 readfile(int fd, int print)
172 {
173 #ifdef _ELF64_SUPPORT
174 uint64_t elf64_go2;
175 #endif /* _ELF64_SUPPORT */
176
177 ssize_t i;
178 int shared = 0;
179
180 if (verbosemode) {
181 dprintf("fd = %x\n", fd);
182 }
183
184 i = xread(fd, (char *)&elfhdr, sizeof (Elf64_Ehdr));
185 if (x.a_magic == ZMAGIC || x.a_magic == NMAGIC)
186 shared = 1;
187 if (i != sizeof (Elf64_Ehdr)) {
188 printf("Error reading ELF header.\n");
189 return (FAIL);
190 }
191 if (!shared && x.a_magic != OMAGIC) {
192 if (*(int *)&elfhdr.e_ident == *(int *)(ELFMAG)) {
193 if (verbosemode) {
194 int is64 = (elfhdr.e_ident[EI_CLASS] ==
195 ELFCLASS64);
196
197 dprintf("calling readelf, elfheader is:\n");
198 dprintf("e_ident\t0x%x, 0x%x, 0x%x, 0x%x\n",
199 *(int *)&elfhdr.e_ident[0],
200 *(int *)&elfhdr.e_ident[4],
201 *(int *)&elfhdr.e_ident[8],
202 *(int *)&elfhdr.e_ident[12]);
203 dprintf("e_machine\t0x%x\n", elfhdr.e_machine);
204
205 dprintf("e_entry\t\t0x%llx\n", (is64 ?
206 elfhdr64.e_entry :
207 (u_longlong_t)elfhdr.e_entry));
208 dprintf("e_shoff\t\t0x%llx\n", (is64 ?
209 elfhdr64.e_shoff :
210 (u_longlong_t)elfhdr.e_shoff));
211 dprintf("e_shnentsize\t%d\n", (is64 ?
212 elfhdr64.e_shentsize : elfhdr.e_shentsize));
213 dprintf("e_shnum\t\t%d\n", (is64 ?
214 elfhdr64.e_shnum : elfhdr.e_shnum));
215 dprintf("e_shstrndx\t%d\n", (is64 ?
216 elfhdr64.e_shstrndx : elfhdr.e_shstrndx));
217 }
218
219
220 #ifdef _ELF64_SUPPORT
221 dprintf("ELF file CLASS 0x%x 32 is %x 64 is %x\n",
222 elfhdr.e_ident[EI_CLASS], ELFCLASS32, ELFCLASS64);
223
224 if (elfhdr.e_ident[EI_CLASS] == ELFCLASS64) {
225 elf64_go2 = read_elf64(fd, print,
226 (Elf64_Ehdr *)&elfhdr);
227
228 return ((elf64_go2 == FAIL_READELF64) ? FAIL :
229 (func_t)elf64_go2);
230
231 } else
232 #endif /* _ELF64_SUPPORT */
233 return (read_elf32(fd, print, &elfhdr));
234 } else {
235 printf("File not executable.\n");
236 return (FAIL);
237 }
238 }
239 return (FAIL);
240 }
241
242 /*
243 * Macros to add attribute/values to the ELF bootstrap vector
244 * and the aux vector. Use the type-cast to convert integers
245 * to pointers first to suppress the gcc warning.
246 */
247 #define AUX(p, a, v) { (p)->a_type = (a); \
248 ((p)++)->a_un.a_val = (int32_t)(uintptr_t)(v); }
249
250 #define EBV(p, a, v) { (p)->eb_tag = (a); \
251 ((p)++)->eb_un.eb_val = (Elf32_Word)(uintptr_t)(v); }
252
253 static func_t
read_elf32(int fd,int print,Elf32_Ehdr * elfhdrp)254 read_elf32(int fd, int print, Elf32_Ehdr *elfhdrp)
255 {
256 Elf32_Phdr *phdr; /* program header */
257 Elf32_Nhdr *nhdr; /* note header */
258 int nphdrs, phdrsize;
259 caddr_t allphdrs;
260 caddr_t namep, descp;
261 Elf32_Addr loadaddr, base;
262 size_t offset = 0;
263 size_t size;
264 uintptr_t off;
265 int i;
266 int bss_seen = 0;
267 int interp = 0; /* interpreter required */
268 static char dlname[MAXPATHLEN]; /* name of interpeter */
269 uint_t dynamic; /* dynamic tags array */
270 Elf32_Phdr *thdr; /* "text" program header */
271 Elf32_Phdr *dhdr; /* "data" program header */
272 func_t entrypt; /* entry point of standalone */
273
274 /* Initialize pointers so we won't free bogus ones on elferror */
275 allphdrs = NULL;
276 nhdr = NULL;
277
278 #ifdef _ELF64_SUPPORT
279 if (verbosemode)
280 printf("Elf32 client\n");
281 #endif /* _ELF64_SUPPORT */
282
283 if (elfhdrp->e_phnum == 0 || elfhdrp->e_phoff == 0)
284 goto elferror;
285
286 /* use uintptr_t to suppress the gcc warning */
287 entrypt = (func_t)(uintptr_t)elfhdrp->e_entry;
288 if (verbosemode)
289 dprintf("Entry point: %p\n", (void *)entrypt);
290
291 /*
292 * Allocate and read in all the program headers.
293 */
294 nphdrs = elfhdrp->e_phnum;
295 phdrsize = nphdrs * elfhdrp->e_phentsize;
296 allphdrs = (caddr_t)kmem_alloc(phdrsize, 0);
297 if (allphdrs == NULL)
298 goto elferror;
299 if (verbosemode)
300 dprintf("lseek: args = %x %x %x\n", fd, elfhdrp->e_phoff, 0);
301 if (lseek(fd, elfhdrp->e_phoff, 0) == -1)
302 goto elferror;
303 if (xread(fd, allphdrs, phdrsize) != phdrsize)
304 goto elferror;
305
306 /*
307 * First look for PT_NOTE headers that tell us what pagesize to
308 * use in allocating program memory.
309 */
310 npagesize = 0;
311 for (i = 0; i < nphdrs; i++) {
312 void *note_buf;
313
314 phdr = (Elf32_Phdr *)(allphdrs + elfhdrp->e_phentsize * i);
315 if (phdr->p_type != PT_NOTE)
316 continue;
317 if (verbosemode) {
318 dprintf("allocating 0x%x bytes for note hdr\n",
319 phdr->p_filesz);
320 }
321 if ((note_buf = kmem_alloc(phdr->p_filesz, 0)) == NULL)
322 goto elferror;
323 if (verbosemode)
324 dprintf("seeking to 0x%x\n", phdr->p_offset);
325 if (lseek(fd, phdr->p_offset, 0) == -1)
326 goto elferror;
327 if (verbosemode) {
328 dprintf("reading 0x%x bytes into %p\n",
329 phdr->p_filesz, (void *)nhdr);
330 }
331 nhdr = (Elf32_Nhdr *)note_buf;
332 if (xread(fd, (caddr_t)nhdr, phdr->p_filesz) != phdr->p_filesz)
333 goto elferror;
334 if (verbosemode) {
335 dprintf("p_note namesz %x descsz %x type %x\n",
336 nhdr->n_namesz, nhdr->n_descsz, nhdr->n_type);
337 }
338
339 /*
340 * Iterate through all ELF PT_NOTE elements looking for
341 * ELF_NOTE_SOLARIS which, if present, will specify the
342 * executable's preferred pagesize.
343 */
344 do {
345 namep = (caddr_t)(nhdr + 1);
346
347 if (nhdr->n_namesz == strlen(ELF_NOTE_SOLARIS) + 1 &&
348 strcmp(namep, ELF_NOTE_SOLARIS) == 0 &&
349 nhdr->n_type == ELF_NOTE_PAGESIZE_HINT) {
350 descp = namep + roundup(nhdr->n_namesz, 4);
351 npagesize = *(int *)descp;
352 if (verbosemode)
353 dprintf("pagesize is %x\n", npagesize);
354 }
355
356 offset += sizeof (Elf32_Nhdr) + roundup(nhdr->n_namesz,
357 4) + roundup(nhdr->n_descsz, 4);
358
359 nhdr = (Elf32_Nhdr *)((char *)note_buf + offset);
360 } while (offset < phdr->p_filesz);
361
362 kmem_free(note_buf, phdr->p_filesz);
363 nhdr = NULL;
364 }
365
366 /*
367 * Next look for PT_LOAD headers to read in.
368 */
369 if (print)
370 printf("Size: ");
371 for (i = 0; i < nphdrs; i++) {
372 phdr = (Elf32_Phdr *)(allphdrs + elfhdrp->e_phentsize * i);
373 if (verbosemode) {
374 dprintf("Doing header 0x%x\n", i);
375 dprintf("phdr\n");
376 dprintf("\tp_offset = %x, p_vaddr = %x\n",
377 phdr->p_offset, phdr->p_vaddr);
378 dprintf("\tp_memsz = %x, p_filesz = %x\n",
379 phdr->p_memsz, phdr->p_filesz);
380 }
381 if (phdr->p_type == PT_LOAD) {
382 if (verbosemode)
383 dprintf("seeking to 0x%x\n", phdr->p_offset);
384 if (lseek(fd, phdr->p_offset, 0) == -1)
385 goto elferror;
386
387 if (phdr->p_flags == (PF_R | PF_W) &&
388 phdr->p_vaddr == 0) {
389 /*
390 * It's a PT_LOAD segment that is RW but
391 * not executable and has a vaddr
392 * of zero. This is relocation info that
393 * doesn't need to stick around after
394 * krtld is done with it. We allocate boot
395 * memory for this segment, since we don't want
396 * it mapped in permanently as part of
397 * the kernel image.
398 */
399 if ((loadaddr = (uintptr_t)
400 kmem_alloc(phdr->p_memsz, 0)) == 0)
401 goto elferror;
402 /*
403 * Save this to pass on
404 * to the interpreter.
405 */
406 phdr->p_vaddr = (Elf32_Addr)loadaddr;
407 } else {
408 if (print)
409 printf("0x%x+", phdr->p_filesz);
410 /*
411 * If we found a new pagesize above, use it
412 * to adjust the memory allocation.
413 */
414 loadaddr = phdr->p_vaddr;
415 if (use_align && npagesize != 0) {
416 off = loadaddr & (npagesize - 1);
417 size = roundup(phdr->p_memsz + off,
418 npagesize);
419 base = loadaddr - off;
420 } else {
421 npagesize = 0;
422 size = phdr->p_memsz;
423 base = loadaddr;
424 }
425 /*
426 * Check if it's text or data.
427 */
428 if (phdr->p_flags & PF_W)
429 dhdr = phdr;
430 else
431 thdr = phdr;
432
433 /*
434 * If memory size is zero just ignore this
435 * header.
436 */
437 if (size == 0)
438 continue;
439
440 if (verbosemode)
441 dprintf("allocating memory: %x %lx "
442 "%x\n", base, size, npagesize);
443 /*
444 * We're all set up to read.
445 * Now let's allocate some memory.
446 */
447
448 /* use uintptr_t to suppress the gcc warning */
449 if (get_progmemory((caddr_t)(uintptr_t)base,
450 size, npagesize))
451 goto elferror;
452 }
453
454 if (verbosemode) {
455 dprintf("reading 0x%x bytes into 0x%x\n",
456 phdr->p_filesz, loadaddr);
457 }
458 /* use uintptr_t to suppress the gcc warning */
459 if (xread(fd, (caddr_t)(uintptr_t)loadaddr,
460 phdr->p_filesz) != phdr->p_filesz)
461 goto elferror;
462
463 /* zero out BSS */
464 if (phdr->p_memsz > phdr->p_filesz) {
465 loadaddr += phdr->p_filesz;
466 if (verbosemode) {
467 dprintf("bss from 0x%x size 0x%x\n",
468 loadaddr,
469 phdr->p_memsz - phdr->p_filesz);
470 }
471 /* use uintptr_t to suppress the gcc warning */
472 bzero((void *)(uintptr_t)loadaddr,
473 phdr->p_memsz - phdr->p_filesz);
474 bss_seen++;
475 if (print)
476 printf("0x%x Bytes\n",
477 phdr->p_memsz - phdr->p_filesz);
478 }
479
480 /* force instructions to be visible to icache */
481 if (phdr->p_flags & PF_X) {
482 sync_instruction_memory(
483 (caddr_t)(uintptr_t)phdr->p_vaddr,
484 phdr->p_memsz);
485 }
486 } else if (phdr->p_type == PT_INTERP) {
487 /*
488 * Dynamically-linked executable.
489 */
490 interp = 1;
491 if (lseek(fd, phdr->p_offset, 0) == -1) {
492 goto elferror;
493 }
494 /*
495 * Get the name of the interpreter.
496 */
497 if (xread(fd, dlname, phdr->p_filesz) !=
498 phdr->p_filesz ||
499 dlname[phdr->p_filesz - 1] != '\0')
500 goto elferror;
501 } else if (phdr->p_type == PT_DYNAMIC) {
502 dynamic = phdr->p_vaddr;
503 }
504 }
505
506 if (!bss_seen && print)
507 printf("0 Bytes\n");
508
509 /*
510 * Load the interpreter
511 * if there is one.
512 */
513 if (interp) {
514 Elf32_Boot bootv[EB_MAX]; /* Bootstrap vector */
515 auxv32_t auxv[__BOOT_NAUXV_IMPL]; /* Aux vector */
516 Elf32_Boot *bv = bootv;
517 auxv32_t *av = auxv;
518 size_t vsize;
519
520 /*
521 * Load it.
522 */
523 if ((entrypt = iload32(dlname, thdr, dhdr, &av)) == FAIL)
524 goto elferror;
525 /*
526 * Build bootstrap and aux vectors.
527 */
528 setup_aux();
529 EBV(bv, EB_AUXV, 0); /* fill in later */
530 EBV(bv, EB_PAGESIZE, pagesize);
531 EBV(bv, EB_DYNAMIC, dynamic);
532 EBV(bv, EB_NULL, 0);
533
534 AUX(av, AT_BASE, entrypt);
535 AUX(av, AT_ENTRY, elfhdrp->e_entry);
536 AUX(av, AT_PAGESZ, pagesize);
537 AUX(av, AT_PHDR, allphdrs);
538 AUX(av, AT_PHNUM, elfhdrp->e_phnum);
539 AUX(av, AT_PHENT, elfhdrp->e_phentsize);
540 if (use_align)
541 AUX(av, AT_SUN_LPAGESZ, npagesize);
542 AUX(av, AT_SUN_IFLUSH, icache_flush);
543 if (cpulist != NULL)
544 AUX(av, AT_SUN_CPU, cpulist);
545 if (mmulist != NULL)
546 AUX(av, AT_SUN_MMU, mmulist);
547 AUX(av, AT_NULL, 0);
548 /*
549 * Realloc vectors and copy them.
550 */
551 vsize = (caddr_t)bv - (caddr_t)bootv;
552 if ((elfbootvec = (Elf32_Boot *)kmem_alloc(vsize, 0)) == NULL)
553 goto elferror;
554 bcopy((char *)bootv, (char *)elfbootvec, vsize);
555
556 size = (caddr_t)av - (caddr_t)auxv;
557 if (size > sizeof (auxv)) {
558 printf("readelf: overrun of available aux vectors\n");
559 kmem_free(elfbootvec, vsize);
560 goto elferror;
561 }
562 /* use uintptr_t to suppress the gcc warning */
563 if ((elfbootvec->eb_un.eb_ptr =
564 (Elf32_Addr)(uintptr_t)kmem_alloc(size, 0)) == 0) {
565 kmem_free(elfbootvec, vsize);
566 goto elferror;
567 }
568 /* use uintptr_t to suppress the gcc warning */
569 bcopy(auxv,
570 (void *)(uintptr_t)(elfbootvec->eb_un.eb_ptr), size);
571
572 #if defined(_ELF64_SUPPORT)
573 /*
574 * Make an LP64 copy of the vector for use by 64-bit standalones
575 * even if they have ELF32.
576 */
577 if ((elfbootvecELF32_64 = (Elf32_Boot *)kmem_alloc(vsize, 0))
578 == NULL)
579 goto elferror;
580 bcopy(bootv, elfbootvecELF32_64, vsize);
581
582 size = (av - auxv) * sizeof (auxv64_t);
583 /* use uintptr_t to suppress the gcc warning */
584 if ((elfbootvecELF32_64->eb_un.eb_ptr =
585 (Elf32_Addr)(uintptr_t)kmem_alloc(size, 0)) == 0) {
586 kmem_free(elfbootvecELF32_64, vsize);
587 goto elferror;
588 } else {
589 auxv64_t *a64 =
590 (auxv64_t *)(uintptr_t)
591 elfbootvecELF32_64->eb_un.eb_ptr;
592 auxv32_t *a = auxv;
593
594 for (a = auxv; a < av; a++) {
595 a64->a_type = a->a_type;
596 a64->a_un.a_val = a->a_un.a_val;
597 a64++;
598 }
599 }
600 #endif /* _ELF64_SUPPORT */
601 } else {
602 kmem_free(allphdrs, phdrsize);
603 }
604 return (entrypt);
605
606 elferror:
607 if (allphdrs != NULL)
608 kmem_free(allphdrs, phdrsize);
609 if (nhdr != NULL)
610 kmem_free(nhdr, phdr->p_filesz);
611 printf("Elf32 read error.\n");
612 return (FAIL);
613 }
614
615 #ifdef _ELF64_SUPPORT
616 /*
617 * Macros to add attribute/values to the ELF bootstrap vector
618 * and the aux vector.
619 */
620 #define AUX64(p, a, v) { (p)->a_type = (a); \
621 ((p)++)->a_un.a_val = (uint64_t)(v); }
622
623 #define EBV64(p, a, v) { (p)->eb_tag = (a); \
624 ((p)++)->eb_un.eb_val = (Elf64_Xword)(v); }
625
626 static uint64_t
read_elf64(int fd,int print,Elf64_Ehdr * elfhdrp)627 read_elf64(int fd, int print, Elf64_Ehdr *elfhdrp)
628 {
629 Elf64_Phdr *phdr; /* program header */
630 Elf64_Nhdr *nhdr; /* note header */
631 int nphdrs, phdrsize;
632 caddr_t allphdrs;
633 caddr_t namep, descp;
634 Elf64_Addr loadaddr, base;
635 size_t offset = 0;
636 size_t size;
637 int i;
638 uintptr_t off;
639 int bss_seen = 0;
640 int interp = 0; /* interpreter required */
641 static char dlname[MAXPATHLEN]; /* name of interpeter */
642 uintptr_t dynamic; /* dynamic tags array */
643 Elf64_Phdr *thdr; /* "text" program header */
644 Elf64_Phdr *dhdr; /* "data" program header */
645 Elf64_Addr entrypt; /* entry point of standalone */
646
647 /* Initialize pointers so we won't free bogus ones on elf64error */
648 allphdrs = NULL;
649 nhdr = NULL;
650 #if defined(__sparcv9)
651 client_isLP64 = 1;
652 #endif /* __sparcv9 */
653
654 if (verbosemode)
655 printf("Elf64 client\n");
656
657 if (elfhdrp->e_phnum == 0 || elfhdrp->e_phoff == 0)
658 goto elf64error;
659
660 entrypt = elfhdrp->e_entry;
661 if (verbosemode)
662 dprintf("Entry point: 0x%llx\n", (u_longlong_t)entrypt);
663
664 /*
665 * Allocate and read in all the program headers.
666 */
667 nphdrs = elfhdrp->e_phnum;
668 phdrsize = nphdrs * elfhdrp->e_phentsize;
669 allphdrs = (caddr_t)kmem_alloc(phdrsize, 0);
670 if (allphdrs == NULL)
671 goto elf64error;
672 if (verbosemode)
673 dprintf("lseek: args = %x %llx %x\n", fd,
674 (u_longlong_t)elfhdrp->e_phoff, 0);
675 if (lseek(fd, elfhdrp->e_phoff, 0) == -1)
676 goto elf64error;
677 if (xread(fd, allphdrs, phdrsize) != phdrsize)
678 goto elf64error;
679
680 /*
681 * First look for PT_NOTE headers that tell us what pagesize to
682 * use in allocating program memory.
683 */
684 npagesize = 0;
685 for (i = 0; i < nphdrs; i++) {
686 void *note_buf;
687
688 phdr = (Elf64_Phdr *)(allphdrs + elfhdrp->e_phentsize * i);
689 if (phdr->p_type != PT_NOTE)
690 continue;
691 if (verbosemode) {
692 dprintf("allocating 0x%llx bytes for note hdr\n",
693 (u_longlong_t)phdr->p_filesz);
694 }
695 if ((note_buf = kmem_alloc(phdr->p_filesz, 0)) == NULL)
696 goto elf64error;
697 if (verbosemode)
698 dprintf("seeking to 0x%llx\n",
699 (u_longlong_t)phdr->p_offset);
700 if (lseek(fd, phdr->p_offset, 0) == -1)
701 goto elf64error;
702 if (verbosemode) {
703 dprintf("reading 0x%llx bytes into 0x%p\n",
704 (u_longlong_t)phdr->p_filesz, (void *)nhdr);
705 }
706 nhdr = (Elf64_Nhdr *)note_buf;
707 if (xread(fd, (caddr_t)nhdr, phdr->p_filesz) != phdr->p_filesz)
708 goto elf64error;
709 if (verbosemode) {
710 dprintf("p_note namesz %x descsz %x type %x\n",
711 nhdr->n_namesz, nhdr->n_descsz, nhdr->n_type);
712 }
713
714 /*
715 * Iterate through all ELF PT_NOTE elements looking for
716 * ELF_NOTE_SOLARIS which, if present, will specify the
717 * executable's preferred pagesize.
718 */
719 do {
720 namep = (caddr_t)(nhdr + 1);
721
722 if (nhdr->n_namesz == strlen(ELF_NOTE_SOLARIS) + 1 &&
723 strcmp(namep, ELF_NOTE_SOLARIS) == 0 &&
724 nhdr->n_type == ELF_NOTE_PAGESIZE_HINT) {
725 descp = namep + roundup(nhdr->n_namesz, 4);
726 npagesize = *(int *)descp;
727 if (verbosemode)
728 dprintf("pagesize is %x\n", npagesize);
729 }
730
731 offset += sizeof (Elf64_Nhdr) + roundup(nhdr->n_namesz,
732 4) + roundup(nhdr->n_descsz, 4);
733
734 nhdr = (Elf64_Nhdr *)((char *)note_buf + offset);
735 } while (offset < phdr->p_filesz);
736
737 kmem_free(note_buf, phdr->p_filesz);
738 nhdr = NULL;
739 }
740
741 /*
742 * Next look for PT_LOAD headers to read in.
743 */
744 if (print)
745 printf("Size: ");
746 for (i = 0; i < nphdrs; i++) {
747 phdr = (Elf64_Phdr *)(allphdrs + elfhdrp->e_phentsize * i);
748 if (verbosemode) {
749 dprintf("Doing header 0x%x\n", i);
750 dprintf("phdr\n");
751 dprintf("\tp_offset = %llx, p_vaddr = %llx\n",
752 (u_longlong_t)phdr->p_offset,
753 (u_longlong_t)phdr->p_vaddr);
754 dprintf("\tp_memsz = %llx, p_filesz = %llx\n",
755 (u_longlong_t)phdr->p_memsz,
756 (u_longlong_t)phdr->p_filesz);
757 dprintf("\tp_type = %x, p_flags = %x\n",
758 phdr->p_type, phdr->p_flags);
759 }
760 if (phdr->p_type == PT_LOAD) {
761 if (verbosemode)
762 dprintf("seeking to 0x%llx\n",
763 (u_longlong_t)phdr->p_offset);
764 if (lseek(fd, phdr->p_offset, 0) == -1)
765 goto elf64error;
766
767 if (phdr->p_flags == (PF_R | PF_W) &&
768 phdr->p_vaddr == 0) {
769 /*
770 * It's a PT_LOAD segment that is RW but
771 * not executable and has a vaddr
772 * of zero. This is relocation info that
773 * doesn't need to stick around after
774 * krtld is done with it. We allocate boot
775 * memory for this segment, since we don't want
776 * it mapped in permanently as part of
777 * the kernel image.
778 */
779 if ((loadaddr = (Elf64_Addr)(uintptr_t)
780 kmem_alloc(phdr->p_memsz, 0)) == 0)
781 goto elf64error;
782
783 /*
784 * Save this to pass on
785 * to the interpreter.
786 */
787 phdr->p_vaddr = loadaddr;
788 } else {
789 if (print)
790 printf("0x%llx+",
791 (u_longlong_t)phdr->p_filesz);
792 /*
793 * If we found a new pagesize above, use it
794 * to adjust the memory allocation.
795 */
796 loadaddr = phdr->p_vaddr;
797 if (use_align && npagesize != 0) {
798 off = loadaddr & (npagesize - 1);
799 size = roundup(phdr->p_memsz + off,
800 npagesize);
801 base = loadaddr - off;
802 } else {
803 npagesize = 0;
804 size = phdr->p_memsz;
805 base = loadaddr;
806 }
807 /*
808 * Check if it's text or data.
809 */
810 if (phdr->p_flags & PF_W)
811 dhdr = phdr;
812 else
813 thdr = phdr;
814
815 if (verbosemode)
816 dprintf(
817 "allocating memory: %llx %lx %x\n",
818 (u_longlong_t)base,
819 size, npagesize);
820
821 /*
822 * If memory size is zero just ignore this
823 * header.
824 */
825 if (size == 0)
826 continue;
827
828 /*
829 * We're all set up to read.
830 * Now let's allocate some memory.
831 */
832 if (get_progmemory((caddr_t)(uintptr_t)base,
833 size, npagesize))
834 goto elf64error;
835 }
836
837 if (verbosemode) {
838 dprintf("reading 0x%llx bytes into 0x%llx\n",
839 (u_longlong_t)phdr->p_filesz,
840 (u_longlong_t)loadaddr);
841 }
842 if (xread(fd, (caddr_t)(uintptr_t)
843 loadaddr, phdr->p_filesz) != phdr->p_filesz)
844 goto elf64error;
845
846 /* zero out BSS */
847 if (phdr->p_memsz > phdr->p_filesz) {
848 loadaddr += phdr->p_filesz;
849 if (verbosemode) {
850 dprintf("bss from 0x%llx size 0x%llx\n",
851 (u_longlong_t)loadaddr,
852 (u_longlong_t)(phdr->p_memsz -
853 phdr->p_filesz));
854 }
855
856 bzero((caddr_t)(uintptr_t)loadaddr,
857 phdr->p_memsz - phdr->p_filesz);
858 bss_seen++;
859 if (print)
860 printf("0x%llx Bytes\n",
861 (u_longlong_t)(phdr->p_memsz -
862 phdr->p_filesz));
863 }
864
865 /* force instructions to be visible to icache */
866 if (phdr->p_flags & PF_X)
867 sync_instruction_memory((caddr_t)(uintptr_t)
868 phdr->p_vaddr, phdr->p_memsz);
869
870 } else if (phdr->p_type == PT_INTERP) {
871 /*
872 * Dynamically-linked executable.
873 */
874 interp = 1;
875 if (lseek(fd, phdr->p_offset, 0) == -1) {
876 goto elf64error;
877 }
878 /*
879 * Get the name of the interpreter.
880 */
881 if (xread(fd, dlname, phdr->p_filesz) !=
882 phdr->p_filesz ||
883 dlname[phdr->p_filesz - 1] != '\0')
884 goto elf64error;
885 } else if (phdr->p_type == PT_DYNAMIC) {
886 dynamic = phdr->p_vaddr;
887 }
888 }
889
890 if (!bss_seen && print)
891 printf("0 Bytes\n");
892
893 /*
894 * Load the interpreter
895 * if there is one.
896 */
897 if (interp) {
898 Elf64_Boot bootv[EB_MAX]; /* Bootstrap vector */
899 auxv64_t auxv[__BOOT_NAUXV_IMPL]; /* Aux vector */
900 Elf64_Boot *bv = bootv;
901 auxv64_t *av = auxv;
902 size_t vsize;
903
904 /*
905 * Load it.
906 */
907 if ((entrypt = iload64(dlname, thdr, dhdr, &av)) ==
908 FAIL_ILOAD64)
909 goto elf64error;
910 /*
911 * Build bootstrap and aux vectors.
912 */
913 setup_aux();
914 EBV64(bv, EB_AUXV, 0); /* fill in later */
915 EBV64(bv, EB_PAGESIZE, pagesize);
916 EBV64(bv, EB_DYNAMIC, dynamic);
917 EBV64(bv, EB_NULL, 0);
918
919 AUX64(av, AT_BASE, entrypt);
920 AUX64(av, AT_ENTRY, elfhdrp->e_entry);
921 AUX64(av, AT_PAGESZ, pagesize);
922 AUX64(av, AT_PHDR, (uintptr_t)allphdrs);
923 AUX64(av, AT_PHNUM, elfhdrp->e_phnum);
924 AUX64(av, AT_PHENT, elfhdrp->e_phentsize);
925 if (npagesize)
926 AUX64(av, AT_SUN_LPAGESZ, npagesize);
927
928 AUX64(av, AT_SUN_IFLUSH, icache_flush);
929 if (cpulist != NULL)
930 AUX64(av, AT_SUN_CPU, (uintptr_t)cpulist);
931 AUX64(av, AT_NULL, 0);
932 /*
933 * Realloc vectors and copy them.
934 */
935 vsize = (caddr_t)bv - (caddr_t)bootv;
936 if ((elfbootvecELF64 =
937 (Elf64_Boot *)kmem_alloc(vsize, 0)) == NULL)
938 goto elf64error;
939 bcopy((char *)bootv, (char *)elfbootvecELF64, vsize);
940
941 size = (caddr_t)av - (caddr_t)auxv;
942 if (size > sizeof (auxv)) {
943 printf("readelf: overrun of available aux vectors\n");
944 kmem_free(elfbootvecELF64, vsize);
945 goto elf64error;
946 }
947
948 if ((elfbootvecELF64->eb_un.eb_ptr =
949 (Elf64_Addr)kmem_alloc(size, 0)) == 0) {
950 kmem_free(elfbootvecELF64, vsize);
951 goto elf64error;
952 }
953
954 bcopy((char *)auxv, (char *)(elfbootvecELF64->eb_un.eb_ptr),
955 size);
956 } else {
957 kmem_free(allphdrs, phdrsize);
958 }
959 return ((uint64_t)entrypt);
960
961 elf64error:
962 if (allphdrs != NULL)
963 kmem_free(allphdrs, phdrsize);
964 if (nhdr != NULL)
965 kmem_free(nhdr, phdr->p_filesz);
966 printf("Elf64 read error.\n");
967 return (FAIL_READELF64);
968 }
969 #endif /* _ELF64_SUPPORT */
970
971 /*
972 * Load the interpreter. It expects a
973 * relocatable .o capable of bootstrapping
974 * itself.
975 */
976 static func_t
iload32(char * rtld,Elf32_Phdr * thdr,Elf32_Phdr * dhdr,auxv32_t ** avp)977 iload32(char *rtld, Elf32_Phdr *thdr, Elf32_Phdr *dhdr, auxv32_t **avp)
978 {
979 Elf32_Ehdr *ehdr = NULL;
980 uintptr_t dl_entry = 0;
981 uint_t i;
982 int fd;
983 int size;
984 caddr_t shdrs = NULL;
985 caddr_t etext, edata;
986
987 /* use uintptr_t to suppress the gcc warning */
988 etext = (caddr_t)(uintptr_t)thdr->p_vaddr + thdr->p_memsz;
989 edata = (caddr_t)(uintptr_t)dhdr->p_vaddr + dhdr->p_memsz;
990
991 /*
992 * Get the module path.
993 */
994 module_path = getmodpath(filename);
995
996 if ((fd = openpath(module_path, rtld, O_RDONLY)) < 0) {
997 printf("boot: cannot find %s\n", rtld);
998 goto errorx;
999 }
1000 dprintf("Opened %s OK\n", rtld);
1001 AUX(*avp, AT_SUN_LDNAME, rtld);
1002 /*
1003 * Allocate and read the ELF header.
1004 */
1005 if ((ehdr = (Elf32_Ehdr *)kmem_alloc(sizeof (Elf32_Ehdr), 0)) == NULL) {
1006 printf("boot: alloc error reading ELF header (%s).\n", rtld);
1007 goto error;
1008 }
1009
1010 if (xread(fd, (char *)ehdr, sizeof (*ehdr)) != sizeof (*ehdr)) {
1011 printf("boot: error reading ELF header (%s).\n", rtld);
1012 goto error;
1013 }
1014
1015 size = ehdr->e_shentsize * ehdr->e_shnum;
1016 if ((shdrs = (caddr_t)kmem_alloc(size, 0)) == NULL) {
1017 printf("boot: alloc error reading ELF header (%s).\n", rtld);
1018 goto error;
1019 }
1020 /*
1021 * Read the section headers.
1022 */
1023 if (lseek(fd, ehdr->e_shoff, 0) == -1 ||
1024 xread(fd, shdrs, size) != size) {
1025 printf("boot: error reading section headers\n");
1026 goto error;
1027 }
1028 AUX(*avp, AT_SUN_LDELF, ehdr);
1029 AUX(*avp, AT_SUN_LDSHDR, shdrs);
1030 /*
1031 * Load sections into the appropriate dynamic segment.
1032 */
1033 for (i = 1; i < ehdr->e_shnum; i++) {
1034 Elf32_Shdr *sp;
1035 caddr_t *spp;
1036 caddr_t load;
1037
1038 sp = (Elf32_Shdr *)(shdrs + (i*ehdr->e_shentsize));
1039 /*
1040 * If it's not allocated and not required
1041 * to do relocation, skip it.
1042 */
1043 if (!(sp->sh_flags & SHF_ALLOC) &&
1044 sp->sh_type != SHT_RELA &&
1045 sp->sh_type != SHT_SYMTAB &&
1046 sp->sh_type != SHT_STRTAB)
1047 continue;
1048 /*
1049 * If the section is read-only,
1050 * it goes in as text.
1051 */
1052 spp = (sp->sh_flags & SHF_WRITE)? &edata: &etext;
1053 /*
1054 * Make some room for it.
1055 */
1056 load = segbrk(spp, sp->sh_size, sp->sh_addralign);
1057 if (load == NULL) {
1058 printf("boot: allocating memory for sections failed\n");
1059 goto error;
1060 }
1061 /*
1062 * Compute the entry point of the linker.
1063 */
1064 if (dl_entry == 0 &&
1065 !(sp->sh_flags & SHF_WRITE) &&
1066 (sp->sh_flags & SHF_EXECINSTR)) {
1067 dl_entry = (uintptr_t)load + ehdr->e_entry;
1068 }
1069 /*
1070 * If it's bss, just zero it out.
1071 */
1072 if (sp->sh_type == SHT_NOBITS) {
1073 bzero(load, sp->sh_size);
1074 } else {
1075 /*
1076 * Read the section contents.
1077 */
1078 if (lseek(fd, sp->sh_offset, 0) == -1 ||
1079 xread(fd, load, sp->sh_size) != sp->sh_size) {
1080 printf("boot: error reading sections\n");
1081 goto error;
1082 }
1083 }
1084 /*
1085 * Assign the section's virtual addr. Use uintptr_t to
1086 * suppress the gcc warning.
1087 */
1088 sp->sh_addr = (Elf32_Off)(uintptr_t)load;
1089 /*
1090 * Force instructions to be visible to icache. Use
1091 * uintptr_t to suppress the gcc warning as well.
1092 */
1093 if (sp->sh_flags & SHF_EXECINSTR)
1094 sync_instruction_memory((caddr_t)(uintptr_t)sp->sh_addr,
1095 sp->sh_size);
1096 }
1097 /*
1098 * Update sizes of segments.
1099 */
1100 thdr->p_memsz = (Elf32_Word)((uintptr_t)etext - thdr->p_vaddr);
1101 dhdr->p_memsz = (Elf32_Word)((uintptr_t)edata - dhdr->p_vaddr);
1102
1103 /* load and relocate symbol tables in SAS */
1104 (void) close(fd);
1105 return ((func_t)dl_entry);
1106
1107 error:
1108 (void) close(fd);
1109 errorx:
1110 if (ehdr)
1111 kmem_free(ehdr, sizeof (Elf32_Ehdr));
1112 if (shdrs)
1113 kmem_free(shdrs, size);
1114 printf("boot: error loading interpreter (%s)\n", rtld);
1115 return (FAIL);
1116 }
1117
1118 #ifdef _ELF64_SUPPORT
1119 /*
1120 * Load the interpreter. It expects a
1121 * relocatable .o capable of bootstrapping
1122 * itself.
1123 */
1124 static Elf64_Addr
iload64(char * rtld,Elf64_Phdr * thdr,Elf64_Phdr * dhdr,auxv64_t ** avp)1125 iload64(char *rtld, Elf64_Phdr *thdr, Elf64_Phdr *dhdr, auxv64_t **avp)
1126 {
1127 Elf64_Ehdr *ehdr = NULL;
1128 Elf64_Addr dl_entry = (Elf64_Addr)0;
1129 Elf64_Addr etext, edata;
1130 uint_t i;
1131 int fd;
1132 int size;
1133 caddr_t shdrs = NULL;
1134
1135 etext = thdr->p_vaddr + thdr->p_memsz;
1136 edata = dhdr->p_vaddr + dhdr->p_memsz;
1137
1138 /*
1139 * Get the module path.
1140 */
1141 module_path = getmodpath(filename);
1142
1143 if ((fd = openpath(module_path, rtld, O_RDONLY)) < 0) {
1144 printf("boot: cannot find %s\n", rtld);
1145 goto errorx;
1146 }
1147 dprintf("Opened %s OK\n", rtld);
1148 AUX64(*avp, AT_SUN_LDNAME, (uintptr_t)rtld);
1149 /*
1150 * Allocate and read the ELF header.
1151 */
1152 if ((ehdr = (Elf64_Ehdr *)kmem_alloc(sizeof (Elf64_Ehdr), 0)) == NULL) {
1153 printf("boot: alloc error reading ELF header (%s).\n", rtld);
1154 goto error;
1155 }
1156
1157 if (xread(fd, (char *)ehdr, sizeof (*ehdr)) != sizeof (*ehdr)) {
1158 printf("boot: error reading ELF header (%s).\n", rtld);
1159 goto error;
1160 }
1161
1162 size = ehdr->e_shentsize * ehdr->e_shnum;
1163 if ((shdrs = (caddr_t)kmem_alloc(size, 0)) == NULL) {
1164 printf("boot: alloc error reading ELF header (%s).\n", rtld);
1165 goto error;
1166 }
1167 /*
1168 * Read the section headers.
1169 */
1170 if (lseek(fd, ehdr->e_shoff, 0) == -1 ||
1171 xread(fd, shdrs, size) != size) {
1172 printf("boot: error reading section headers\n");
1173 goto error;
1174 }
1175
1176 AUX64(*avp, AT_SUN_LDELF, ehdr);
1177 AUX64(*avp, AT_SUN_LDSHDR, shdrs);
1178
1179 /*
1180 * Load sections into the appropriate dynamic segment.
1181 */
1182 for (i = 1; i < ehdr->e_shnum; i++) {
1183 Elf64_Shdr *sp;
1184 Elf64_Addr *spp, load;
1185
1186 sp = (Elf64_Shdr *)(shdrs + (i*ehdr->e_shentsize));
1187 /*
1188 * If it's not allocated and not required
1189 * to do relocation, skip it.
1190 */
1191 if (!(sp->sh_flags & SHF_ALLOC) &&
1192 sp->sh_type != SHT_SYMTAB &&
1193 sp->sh_type != SHT_STRTAB &&
1194 sp->sh_type != SHT_RELA)
1195 continue;
1196 /*
1197 * If the section is read-only,
1198 * it goes in as text.
1199 */
1200 spp = (sp->sh_flags & SHF_WRITE)? &edata: &etext;
1201
1202 /*
1203 * Make some room for it.
1204 */
1205 load = (Elf64_Addr)segbrk((caddr_t *)spp, sp->sh_size,
1206 sp->sh_addralign);
1207
1208 if (load == 0) {
1209 printf("boot: allocating memory for section %d "
1210 "failed\n", i);
1211 goto error;
1212 }
1213
1214 /*
1215 * Compute the entry point of the linker.
1216 */
1217 if (dl_entry == 0 &&
1218 !(sp->sh_flags & SHF_WRITE) &&
1219 (sp->sh_flags & SHF_EXECINSTR)) {
1220 dl_entry = load + ehdr->e_entry;
1221 if (verbosemode)
1222 dprintf("boot: loading linker @ 0x%llx\n",
1223 (u_longlong_t)dl_entry);
1224 }
1225
1226 /*
1227 * If it's bss, just zero it out.
1228 */
1229 if (sp->sh_type == SHT_NOBITS) {
1230 bzero((caddr_t)(uintptr_t)load, sp->sh_size);
1231 } else {
1232 /*
1233 * Read the section contents.
1234 */
1235 if (lseek(fd, sp->sh_offset, 0) == -1 ||
1236 xread(fd, (caddr_t)(uintptr_t)load, sp->sh_size) !=
1237 sp->sh_size) {
1238 printf("boot: error reading section %d\n", i);
1239 goto error;
1240 }
1241 }
1242 /*
1243 * Assign the section's virtual addr.
1244 */
1245
1246 sp->sh_addr = load;
1247
1248 if (verbosemode)
1249 dprintf("boot: section %d, type %d, loaded @ 0x%llx, "
1250 "size 0x%llx\n", i, sp->sh_type, (u_longlong_t)load,
1251 (u_longlong_t)sp->sh_size);
1252
1253 /* force instructions to be visible to icache */
1254 if (sp->sh_flags & SHF_EXECINSTR)
1255 sync_instruction_memory((caddr_t)(uintptr_t)sp->sh_addr,
1256 sp->sh_size);
1257 }
1258 /*
1259 * Update sizes of segments.
1260 */
1261 thdr->p_memsz = etext - thdr->p_vaddr;
1262 dhdr->p_memsz = edata - dhdr->p_vaddr;
1263
1264 /* load and relocate symbol tables in SAS */
1265 (void) close(fd);
1266 return (dl_entry);
1267
1268 error:
1269 (void) close(fd);
1270 errorx:
1271 if (ehdr)
1272 kmem_free((caddr_t)ehdr, sizeof (Elf64_Ehdr));
1273 if (shdrs)
1274 kmem_free(shdrs, size);
1275 printf("boot: error loading interpreter (%s)\n", rtld);
1276 return (FAIL_ILOAD64);
1277 }
1278 #endif /* _ELF64_SUPPORT */
1279
1280 /*
1281 * Extend the segment's "break" value by bytes.
1282 */
1283 static caddr_t
segbrk(caddr_t * spp,size_t bytes,size_t align)1284 segbrk(caddr_t *spp, size_t bytes, size_t align)
1285 {
1286 caddr_t va, pva;
1287 size_t size = 0;
1288 unsigned int alloc_pagesize = pagesize;
1289 unsigned int alloc_align = 0;
1290
1291 if (npagesize) {
1292 alloc_align = npagesize;
1293 alloc_pagesize = npagesize;
1294 }
1295
1296 va = (caddr_t)ALIGN(*spp, align);
1297 pva = (caddr_t)roundup((uintptr_t)*spp, alloc_pagesize);
1298 /*
1299 * Need more pages?
1300 */
1301 if (va + bytes > pva) {
1302 size = roundup((bytes - (pva - va)), alloc_pagesize);
1303
1304 if (get_progmemory(pva, size, alloc_align)) {
1305 printf("boot: segbrk allocation failed, "
1306 "0x%lx bytes @ %p\n", bytes, (void *)pva);
1307 return (NULL);
1308 }
1309 }
1310 *spp = va + bytes;
1311
1312 return (va);
1313 }
1314
1315 /*
1316 * Open the file using a search path and
1317 * return the file descriptor (or -1 on failure).
1318 */
1319 static int
openpath(char * path,char * fname,int flags)1320 openpath(char *path, char *fname, int flags)
1321 {
1322 register char *p, *q;
1323 char buf[MAXPATHLEN];
1324 int fd;
1325
1326 /*
1327 * If the file name is absolute,
1328 * don't use the module search path.
1329 */
1330 if (fname[0] == '/')
1331 return (open(fname, flags));
1332
1333 q = NULL;
1334 for (p = path; /* forever */; p = q) {
1335
1336 while (*p == ' ' || *p == '\t' || *p == ':')
1337 p++;
1338 if (*p == '\0')
1339 break;
1340 q = p;
1341 while (*q && *q != ' ' && *q != '\t' && *q != ':')
1342 q++;
1343 (void) strncpy(buf, p, q - p);
1344 if (q[-1] != '/') {
1345 buf[q - p] = '/';
1346 (void) strcpy(&buf[q - p + 1], fname);
1347 } else {
1348 /*
1349 * This checks for paths that end in '/'
1350 */
1351 (void) strcpy(&buf[q - p], fname);
1352 }
1353
1354 if ((fd = open(buf, flags)) > 0)
1355 return (fd);
1356 }
1357 return (-1);
1358 }
1359
1360 /*
1361 * Get the module search path.
1362 */
1363 static char *
getmodpath(char * fname)1364 getmodpath(char *fname)
1365 {
1366 register char *p = strrchr(fname, '/');
1367 static char mod_path[MOD_MAXPATH];
1368 size_t len;
1369 extern char *impl_arch_name;
1370 #if defined(__sparcv9)
1371 char *isastr = "/sparcv9";
1372 size_t isalen = strlen(isastr);
1373 #endif /* __sparcv9 */
1374
1375 if (p == NULL) {
1376 /* strchr could not find a "/" */
1377 printf("%s is not a legal kernel pathname", fname);
1378 return (NULL);
1379 }
1380 while (p > fname && *(p - 1) == '/')
1381 p--; /* remove trailing "/"s */
1382 if (p == fname)
1383 p++; /* "/" is the modpath in this case */
1384
1385 len = p - fname;
1386 (void) strncpy(mod_path, fname, len);
1387 mod_path[len] = 0;
1388
1389 #if defined(__sparcv9)
1390 len = strlen(mod_path);
1391 if ((len > isalen) && (strcmp(&mod_path[len - isalen], isastr) == 0)) {
1392 mod_path[len - isalen] = '\0';
1393 if ((client_isLP64 == 0) && verbosemode)
1394 printf("Assuming LP64 %s client.\n", isastr);
1395 client_isLP64 = 1;
1396 }
1397 #endif /* __sparcv9 */
1398 mod_path_uname_m(mod_path, impl_arch_name);
1399 (void) strcat(mod_path, " ");
1400 (void) strcat(mod_path, MOD_DEFPATH);
1401
1402 if (boothowto & RB_ASKNAME) {
1403 char buf[MOD_MAXPATH];
1404
1405 printf("Enter default directory for modules [%s]: ", mod_path);
1406 (void) cons_gets(buf, sizeof (buf));
1407 if (buf[0] != '\0')
1408 (void) strcpy(mod_path, buf);
1409 }
1410 if (verbosemode)
1411 printf("modpath: %s\n", mod_path);
1412 return (mod_path);
1413 }
1414