dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / psm / stand / boot / common / readfile.c
blob4e4350c318252b10b0c56095d90418f91a0f0c83
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
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>
42 #include "util.h"
44 #ifdef BOOTAMD64
45 #include <amd64/amd64_page.h>
46 #endif /* BOOTAMD64 */
48 union {
49 struct exec X;
50 Elf32_Ehdr Elfhdr;
51 Elf64_Ehdr Elfhdr64;
52 } ex;
54 #define x ex.X
55 #define elfhdr ex.Elfhdr
56 #define elfhdr64 ex.Elfhdr64
58 typedef int (*func_t)();
60 #define FAIL ((func_t)-1)
61 #define ALIGN(x, a) \
62 ((a) == 0 ? (uintptr_t)(x) : (((uintptr_t)(x) + (a) - 1) & ~((a) - 1)))
64 #define __BOOT_NAUXV_IMPL 22
66 int use_align = 0;
67 int npagesize = 0;
68 uint_t icache_flush = 0;
69 char *cpulist = NULL;
70 char *mmulist = NULL;
71 char *module_path; /* path for kernel modules */
74 * This file gets compiled in LP64 (for sun4u) and ILP32 models.
75 * For LP64 compilation, the "client" file we load and run may be LP64 or ILP32,
76 * and during bringup, the LP64 clients may have ELF32 headers.
78 #ifdef _ELF64_SUPPORT
79 #ifndef BOOTAMD64
81 * Bootstrap vector for ELF32 LP64 client - neither supported nor needed for
82 * AMD64
84 Elf32_Boot *elfbootvecELF32_64;
85 #endif /* !BOOTAMD64 */
87 Elf64_Boot *elfbootvecELF64; /* ELF bootstrap vector for Elf64 LP64 */
89 #define OK ((func_t)0)
91 #define FAIL_READELF64 ((uint64_t)0)
92 #define FAIL_ILOAD64 ((Elf64_Addr)-1)
93 #endif /* _ELF64_SUPPORT */
96 * And by an ILP32 client. The non-sun4u/LP64 booters use these.
97 * Also, the sun4u booter must create this for ILP32 clients.
99 Elf32_Boot *elfbootvec; /* ELF bootstrap vector normal ILP32 */
102 * Read in a Unix executable file and return its entry point.
103 * Handle the various a.out formats correctly.
104 * "fd" is the standalone file descriptor to read from.
105 * Print informative little messages if "print" is on.
106 * Returns -1 for errors.
109 #ifdef DEBUG
110 static int debug = 1;
111 #else /* DEBUG */
112 static int debug = 0;
113 #endif /* DEBUG */
115 #define dprintf if (debug) printf
117 #ifdef _ELF64_SUPPORT
118 typedef struct {
119 uint_t a_type;
120 #ifdef BOOTAMD64
121 uint_t a_pad; /* needed to 8-byte align uint64_ts below for AMD64 */
122 #endif /* BOOTAMD64 */
123 union {
124 uint64_t a_val;
125 uint64_t a_ptr;
126 #ifndef BOOTAMD64
127 void (*a_fcn)(); /* XXX - UNUSED? */
128 #endif /* !BOOTAMD64 */
129 } a_un;
130 } auxv64_t;
132 #if defined(__sparcv9)
133 extern int client_isLP64;
134 #endif /* __sparcv9 */
136 static uint64_t read_elf64(int, int, Elf64_Ehdr *);
137 static Elf64_Addr iload64(char *, Elf64_Phdr *, Elf64_Phdr *, auxv64_t **);
138 #endif /* _ELF64_SUPPORT */
140 #if defined(i386) && !defined(_SYSCALL32)
141 typedef auxv_t auxv32_t;
142 #endif
144 static func_t read_elf32(int, int, Elf32_Ehdr *);
145 static func_t iload32(char *, Elf32_Phdr *, Elf32_Phdr *, auxv32_t **);
146 static caddr_t segbrk(caddr_t *, size_t, size_t);
147 static int openpath(char *, char *, int);
148 static char *getmodpath(char *);
149 extern void setup_aux(void);
151 extern void *kmem_alloc(size_t, int);
152 extern void kmem_free(void *, size_t);
153 extern int cons_gets(char *, int);
155 #ifdef BOOTAMD64
156 extern const char *amd64_getmmulist(void);
158 extern int amd64_elf64;
159 extern int is_amd64;
160 #endif /* BOOTAMD64 */
162 extern void sync_instruction_memory(caddr_t v, size_t len);
164 extern int verbosemode;
165 extern int boothowto;
166 extern int pagesize;
167 extern char filename[];
170 * repeat reads (forever) until size of request is satisfied
171 * (Thus, you don't want to use this cases where short reads are ok)
173 ssize_t
174 xread(int fd, char *p, size_t nbytes)
176 size_t bytesread = 0;
177 int errorcount = 0;
178 ssize_t i;
180 while (bytesread < nbytes) {
181 i = read(fd, p, nbytes - bytesread);
182 if (i < 0) {
183 ++errorcount;
184 if (verbosemode)
185 printf("read error (0x%x times)\n", errorcount);
186 continue;
188 bytesread += i;
189 p += i;
191 return (bytesread);
194 func_t
195 readfile(int fd, int print)
197 #ifdef _ELF64_SUPPORT
198 #ifdef BOOTAMD64
199 extern int bsetprop(struct bootops *, char *, void *, int);
200 extern struct bootops *bop;
201 extern uint64_t elf64_go2;
202 #else /* !BOOTAMD64 */
203 uint64_t elf64_go2;
204 #endif /* BOOTAMD64 */
205 #endif /* _ELF64_SUPPORT */
207 ssize_t i;
208 int shared = 0;
210 if (verbosemode) {
211 dprintf("fd = %x\n", fd);
214 i = xread(fd, (char *)&elfhdr, sizeof (Elf64_Ehdr));
215 if (x.a_magic == ZMAGIC || x.a_magic == NMAGIC)
216 shared = 1;
217 if (i != sizeof (Elf64_Ehdr)) {
218 printf("Error reading ELF header.\n");
219 return (FAIL);
221 if (!shared && x.a_magic != OMAGIC) {
222 if (*(int *)&elfhdr.e_ident == *(int *)(ELFMAG)) {
223 if (verbosemode) {
224 int is64 = (elfhdr.e_ident[EI_CLASS] ==
225 ELFCLASS64);
227 dprintf("calling readelf, elfheader is:\n");
228 dprintf("e_ident\t0x%x, 0x%x, 0x%x, 0x%x\n",
229 *(int *)&elfhdr.e_ident[0],
230 *(int *)&elfhdr.e_ident[4],
231 *(int *)&elfhdr.e_ident[8],
232 *(int *)&elfhdr.e_ident[12]);
233 dprintf("e_machine\t0x%x\n", elfhdr.e_machine);
235 dprintf("e_entry\t\t0x%llx\n", (is64 ?
236 elfhdr64.e_entry :
237 (u_longlong_t)elfhdr.e_entry));
238 dprintf("e_shoff\t\t0x%llx\n", (is64 ?
239 elfhdr64.e_shoff :
240 (u_longlong_t)elfhdr.e_shoff));
241 dprintf("e_shnentsize\t%d\n", (is64 ?
242 elfhdr64.e_shentsize : elfhdr.e_shentsize));
243 dprintf("e_shnum\t\t%d\n", (is64 ?
244 elfhdr64.e_shnum : elfhdr.e_shnum));
245 dprintf("e_shstrndx\t%d\n", (is64 ?
246 elfhdr64.e_shstrndx : elfhdr.e_shstrndx));
250 #ifdef _ELF64_SUPPORT
251 dprintf("ELF file CLASS 0x%x 32 is %x 64 is %x\n",
252 elfhdr.e_ident[EI_CLASS], ELFCLASS32, ELFCLASS64);
254 if (elfhdr.e_ident[EI_CLASS] == ELFCLASS64) {
255 #ifdef BOOTAMD64
256 if (elfhdr.e_machine != EM_AMD64) {
257 printf("FATAL: 64-bit ELF executable "
258 "not for AMD64\n (e_machine "
259 "= %d).\n", elfhdr.e_machine);
260 return (FAIL);
264 * OK, we know the executable is for an AMD64
265 * CPU. Make sure we ARE an AMD64 CPU before
266 * proceeding.
268 if (is_amd64 == 0) {
269 printf("FATAL: AMD64 executables not "
270 " supported on this CPU.\n");
271 return (FAIL);
274 amd64_elf64 = (elfhdr.e_ident[EI_CLASS] ==
275 ELFCLASS64);
276 #endif /* BOOTAMD64 */
278 elf64_go2 = read_elf64(fd, print,
279 (Elf64_Ehdr *)&elfhdr);
281 #ifdef BOOTAMD64
282 if (elf64_go2 != FAIL_READELF64)
283 (void) bsetprop(bop, "mmu-modlist",
284 "mmu64", 0);
286 return ((elf64_go2 == FAIL_READELF64) ? FAIL :
287 OK);
288 #else /* !BOOTAMD64 */
289 return ((elf64_go2 == FAIL_READELF64) ? FAIL :
290 (func_t)elf64_go2);
291 #endif /* BOOTAMD64 */
293 } else
294 #endif /* _ELF64_SUPPORT */
295 return (read_elf32(fd, print, &elfhdr));
296 } else {
297 printf("File not executable.\n");
298 return (FAIL);
301 return (FAIL);
305 * Macros to add attribute/values to the ELF bootstrap vector
306 * and the aux vector. Use the type-cast to convert integers
307 * to pointers first to suppress the gcc warning.
309 #define AUX(p, a, v) { (p)->a_type = (a); \
310 ((p)++)->a_un.a_val = (int32_t)(uintptr_t)(v); }
312 #define EBV(p, a, v) { (p)->eb_tag = (a); \
313 ((p)++)->eb_un.eb_val = (Elf32_Word)(uintptr_t)(v); }
315 static func_t
316 read_elf32(int fd, int print, Elf32_Ehdr *elfhdrp)
318 Elf32_Phdr *phdr; /* program header */
319 Elf32_Nhdr *nhdr; /* note header */
320 int nphdrs, phdrsize;
321 caddr_t allphdrs;
322 caddr_t namep, descp;
323 Elf32_Addr loadaddr, base;
324 size_t offset = 0;
325 size_t size;
326 uintptr_t off;
327 int i;
328 int bss_seen = 0;
329 int interp = 0; /* interpreter required */
330 static char dlname[MAXPATHLEN]; /* name of interpeter */
331 uint_t dynamic; /* dynamic tags array */
332 Elf32_Phdr *thdr; /* "text" program header */
333 Elf32_Phdr *dhdr; /* "data" program header */
334 func_t entrypt; /* entry point of standalone */
336 /* Initialize pointers so we won't free bogus ones on elferror */
337 allphdrs = NULL;
338 nhdr = NULL;
340 #ifdef _ELF64_SUPPORT
341 if (verbosemode)
342 printf("Elf32 client\n");
343 #endif /* _ELF64_SUPPORT */
345 if (elfhdrp->e_phnum == 0 || elfhdrp->e_phoff == 0)
346 goto elferror;
348 /* use uintptr_t to suppress the gcc warning */
349 entrypt = (func_t)(uintptr_t)elfhdrp->e_entry;
350 if (verbosemode)
351 dprintf("Entry point: %p\n", (void *)entrypt);
354 * Allocate and read in all the program headers.
356 nphdrs = elfhdrp->e_phnum;
357 phdrsize = nphdrs * elfhdrp->e_phentsize;
358 allphdrs = kmem_alloc(phdrsize, 0);
359 if (allphdrs == NULL)
360 goto elferror;
361 if (verbosemode)
362 dprintf("lseek: args = %x %x %x\n", fd, elfhdrp->e_phoff, 0);
363 if (lseek(fd, elfhdrp->e_phoff, 0) == -1)
364 goto elferror;
365 if (xread(fd, allphdrs, phdrsize) != phdrsize)
366 goto elferror;
369 * First look for PT_NOTE headers that tell us what pagesize to
370 * use in allocating program memory.
372 npagesize = 0;
373 for (i = 0; i < nphdrs; i++) {
374 void *note_buf;
376 phdr = (Elf32_Phdr *)(allphdrs + elfhdrp->e_phentsize * i);
377 if (phdr->p_type != PT_NOTE)
378 continue;
379 if (verbosemode) {
380 dprintf("allocating 0x%x bytes for note hdr\n",
381 phdr->p_filesz);
383 if ((note_buf = kmem_alloc(phdr->p_filesz, 0)) == NULL)
384 goto elferror;
385 if (verbosemode)
386 dprintf("seeking to 0x%x\n", phdr->p_offset);
387 if (lseek(fd, phdr->p_offset, 0) == -1)
388 goto elferror;
389 if (verbosemode) {
390 dprintf("reading 0x%x bytes into %p\n",
391 phdr->p_filesz, (void *)nhdr);
393 nhdr = (Elf32_Nhdr *)note_buf;
394 if (xread(fd, (caddr_t)nhdr, phdr->p_filesz) != phdr->p_filesz)
395 goto elferror;
396 if (verbosemode) {
397 dprintf("p_note namesz %x descsz %x type %x\n",
398 nhdr->n_namesz, nhdr->n_descsz, nhdr->n_type);
402 * Iterate through all ELF PT_NOTE elements looking for
403 * ELF_NOTE_SOLARIS which, if present, will specify the
404 * executable's preferred pagesize.
406 do {
407 namep = (caddr_t)(nhdr + 1);
409 if (nhdr->n_namesz == strlen(ELF_NOTE_SOLARIS) + 1 &&
410 strcmp(namep, ELF_NOTE_SOLARIS) == 0 &&
411 nhdr->n_type == ELF_NOTE_PAGESIZE_HINT) {
412 descp = namep + roundup(nhdr->n_namesz, 4);
413 npagesize = *(int *)descp;
414 if (verbosemode)
415 dprintf("pagesize is %x\n", npagesize);
418 offset += sizeof (Elf32_Nhdr) + roundup(nhdr->n_namesz,
419 4) + roundup(nhdr->n_descsz, 4);
421 nhdr = (Elf32_Nhdr *)((char *)note_buf + offset);
422 } while (offset < phdr->p_filesz);
424 kmem_free(note_buf, phdr->p_filesz);
425 nhdr = NULL;
429 * Next look for PT_LOAD headers to read in.
431 if (print)
432 printf("Size: ");
433 for (i = 0; i < nphdrs; i++) {
434 phdr = (Elf32_Phdr *)(allphdrs + elfhdrp->e_phentsize * i);
435 if (verbosemode) {
436 dprintf("Doing header 0x%x\n", i);
437 dprintf("phdr\n");
438 dprintf("\tp_offset = %x, p_vaddr = %x\n",
439 phdr->p_offset, phdr->p_vaddr);
440 dprintf("\tp_memsz = %x, p_filesz = %x\n",
441 phdr->p_memsz, phdr->p_filesz);
443 if (phdr->p_type == PT_LOAD) {
444 if (verbosemode)
445 dprintf("seeking to 0x%x\n", phdr->p_offset);
446 if (lseek(fd, phdr->p_offset, 0) == -1)
447 goto elferror;
449 if (phdr->p_flags == (PF_R | PF_W) &&
450 phdr->p_vaddr == 0) {
452 * It's a PT_LOAD segment that is RW but
453 * not executable and has a vaddr
454 * of zero. This is relocation info that
455 * doesn't need to stick around after
456 * krtld is done with it. We allocate boot
457 * memory for this segment, since we don't want
458 * it mapped in permanently as part of
459 * the kernel image.
461 if ((loadaddr = (uintptr_t)
462 kmem_alloc(phdr->p_memsz, 0)) == NULL)
463 goto elferror;
465 * Save this to pass on
466 * to the interpreter.
468 phdr->p_vaddr = (Elf32_Addr)loadaddr;
469 } else {
470 if (print)
471 printf("0x%x+", phdr->p_filesz);
473 * If we found a new pagesize above, use it
474 * to adjust the memory allocation.
476 loadaddr = phdr->p_vaddr;
477 if (use_align && npagesize != 0) {
478 off = loadaddr & (npagesize - 1);
479 size = roundup(phdr->p_memsz + off,
480 npagesize);
481 base = loadaddr - off;
482 } else {
483 npagesize = 0;
484 size = phdr->p_memsz;
485 base = loadaddr;
488 * Check if it's text or data.
490 if (phdr->p_flags & PF_W)
491 dhdr = phdr;
492 else
493 thdr = phdr;
496 * If memory size is zero just ignore this
497 * header.
499 if (size == 0)
500 continue;
502 if (verbosemode)
503 dprintf("allocating memory: %x %lx "
504 "%x\n", base, size, npagesize);
506 * We're all set up to read.
507 * Now let's allocate some memory.
510 #ifdef i386
512 * If vaddr == paddr and npagesize is 0, that
513 * means the executable needs to be identity
514 * mapped in memory (va == pa, mapped 1:1)
516 * Otherwise load as usual.
518 if ((phdr->p_vaddr == phdr->p_paddr) &&
519 (npagesize == 0)) {
520 extern caddr_t idmap_mem(uint32_t,
521 size_t, int);
523 uint_t n;
525 n = (uint_t)base & (pagesize - 1);
526 if (n) {
527 base -= n;
528 size += n;
531 if (!idmap_mem((uint32_t)base,
532 (size_t)size, pagesize))
533 goto elferror;
534 } else
535 #endif /* i386 */
536 /* use uintptr_t to suppress the gcc warning */
537 if (get_progmemory((caddr_t)(uintptr_t)base,
538 size, npagesize))
539 goto elferror;
542 if (verbosemode) {
543 dprintf("reading 0x%x bytes into 0x%x\n",
544 phdr->p_filesz, loadaddr);
546 /* use uintptr_t to suppress the gcc warning */
547 if (xread(fd, (caddr_t)(uintptr_t)loadaddr,
548 phdr->p_filesz) != phdr->p_filesz)
549 goto elferror;
551 /* zero out BSS */
552 if (phdr->p_memsz > phdr->p_filesz) {
553 loadaddr += phdr->p_filesz;
554 if (verbosemode) {
555 dprintf("bss from 0x%x size 0x%x\n",
556 loadaddr,
557 phdr->p_memsz - phdr->p_filesz);
559 /* use uintptr_t to suppress the gcc warning */
560 bzero((void *)(uintptr_t)loadaddr,
561 phdr->p_memsz - phdr->p_filesz);
562 bss_seen++;
563 if (print)
564 printf("0x%x Bytes\n",
565 phdr->p_memsz - phdr->p_filesz);
568 /* force instructions to be visible to icache */
569 if (phdr->p_flags & PF_X) {
570 sync_instruction_memory(
571 (caddr_t)(uintptr_t)phdr->p_vaddr,
572 phdr->p_memsz);
574 } else if (phdr->p_type == PT_INTERP) {
576 * Dynamically-linked executable.
578 interp = 1;
579 if (lseek(fd, phdr->p_offset, 0) == -1) {
580 goto elferror;
583 * Get the name of the interpreter.
585 if (xread(fd, dlname, phdr->p_filesz) !=
586 phdr->p_filesz ||
587 dlname[phdr->p_filesz - 1] != '\0')
588 goto elferror;
589 } else if (phdr->p_type == PT_DYNAMIC) {
590 dynamic = phdr->p_vaddr;
594 if (!bss_seen && print)
595 printf("0 Bytes\n");
598 * Load the interpreter
599 * if there is one.
601 if (interp) {
602 Elf32_Boot bootv[EB_MAX]; /* Bootstrap vector */
603 auxv32_t auxv[__BOOT_NAUXV_IMPL]; /* Aux vector */
604 Elf32_Boot *bv = bootv;
605 auxv32_t *av = auxv;
606 size_t vsize;
609 * Load it.
611 if ((entrypt = iload32(dlname, thdr, dhdr, &av)) == FAIL)
612 goto elferror;
614 * Build bootstrap and aux vectors.
616 setup_aux();
617 EBV(bv, EB_AUXV, 0); /* fill in later */
618 EBV(bv, EB_PAGESIZE, pagesize);
619 EBV(bv, EB_DYNAMIC, dynamic);
620 EBV(bv, EB_NULL, 0);
622 AUX(av, AT_BASE, entrypt);
623 AUX(av, AT_ENTRY, elfhdrp->e_entry);
624 AUX(av, AT_PAGESZ, pagesize);
625 AUX(av, AT_PHDR, allphdrs);
626 AUX(av, AT_PHNUM, elfhdrp->e_phnum);
627 AUX(av, AT_PHENT, elfhdrp->e_phentsize);
628 if (use_align)
629 AUX(av, AT_SUN_LPAGESZ, npagesize);
630 AUX(av, AT_SUN_IFLUSH, icache_flush);
631 if (cpulist != NULL)
632 AUX(av, AT_SUN_CPU, cpulist);
633 if (mmulist != NULL)
634 AUX(av, AT_SUN_MMU, mmulist);
635 AUX(av, AT_NULL, 0);
637 * Realloc vectors and copy them.
639 vsize = (caddr_t)bv - (caddr_t)bootv;
640 if ((elfbootvec = (Elf32_Boot *)kmem_alloc(vsize, 0)) == NULL)
641 goto elferror;
642 bcopy((char *)bootv, (char *)elfbootvec, vsize);
644 size = (caddr_t)av - (caddr_t)auxv;
645 if (size > sizeof (auxv)) {
646 printf("readelf: overrun of available aux vectors\n");
647 kmem_free(elfbootvec, vsize);
648 goto elferror;
650 /* use uintptr_t to suppress the gcc warning */
651 if ((elfbootvec->eb_un.eb_ptr =
652 (Elf32_Addr)(uintptr_t)kmem_alloc(size, 0)) == NULL) {
653 kmem_free(elfbootvec, vsize);
654 goto elferror;
656 /* use uintptr_t to suppress the gcc warning */
657 bcopy(auxv,
658 (void *)(uintptr_t)(elfbootvec->eb_un.eb_ptr), size);
660 #if defined(_ELF64_SUPPORT) && !defined(BOOTAMD64)
662 * Make an LP64 copy of the vector for use by 64-bit standalones
663 * even if they have ELF32.
665 if ((elfbootvecELF32_64 = (Elf32_Boot *)kmem_alloc(vsize, 0))
666 == NULL)
667 goto elferror;
668 bcopy(bootv, elfbootvecELF32_64, vsize);
670 size = (av - auxv) * sizeof (auxv64_t);
671 /* use uintptr_t to suppress the gcc warning */
672 if ((elfbootvecELF32_64->eb_un.eb_ptr =
673 (Elf32_Addr)(uintptr_t)kmem_alloc(size, 0)) == NULL) {
674 kmem_free(elfbootvecELF32_64, vsize);
675 goto elferror;
676 } else {
677 auxv64_t *a64 =
678 (auxv64_t *)(uintptr_t)
679 elfbootvecELF32_64->eb_un.eb_ptr;
680 auxv32_t *a = auxv;
682 for (a = auxv; a < av; a++) {
683 a64->a_type = a->a_type;
684 a64->a_un.a_val = a->a_un.a_val;
685 a64++;
688 #endif /* _ELF64_SUPPORT && !BOOTAMD64 */
689 } else {
690 kmem_free(allphdrs, phdrsize);
692 return (entrypt);
694 elferror:
695 if (allphdrs != NULL)
696 kmem_free(allphdrs, phdrsize);
697 if (nhdr != NULL)
698 kmem_free(nhdr, phdr->p_filesz);
699 printf("Elf32 read error.\n");
700 return (FAIL);
703 #ifdef _ELF64_SUPPORT
705 * Macros to add attribute/values to the ELF bootstrap vector
706 * and the aux vector.
708 #define AUX64(p, a, v) { (p)->a_type = (a); \
709 ((p)++)->a_un.a_val = (uint64_t)(v); }
711 #define EBV64(p, a, v) { (p)->eb_tag = (a); \
712 ((p)++)->eb_un.eb_val = (Elf64_Xword)(v); }
714 static uint64_t
715 read_elf64(int fd, int print, Elf64_Ehdr *elfhdrp)
717 Elf64_Phdr *phdr; /* program header */
718 Elf64_Nhdr *nhdr; /* note header */
719 int nphdrs, phdrsize;
720 caddr_t allphdrs;
721 caddr_t namep, descp;
722 Elf64_Addr loadaddr, base;
723 size_t offset = 0;
724 size_t size;
725 int i;
726 uintptr_t off;
727 int bss_seen = 0;
728 int interp = 0; /* interpreter required */
729 static char dlname[MAXPATHLEN]; /* name of interpeter */
730 uintptr_t dynamic; /* dynamic tags array */
731 Elf64_Phdr *thdr; /* "text" program header */
732 Elf64_Phdr *dhdr; /* "data" program header */
733 Elf64_Addr entrypt; /* entry point of standalone */
735 /* Initialize pointers so we won't free bogus ones on elf64error */
736 allphdrs = NULL;
737 nhdr = NULL;
738 #if defined(__sparcv9)
739 client_isLP64 = 1;
740 #endif /* __sparcv9 */
742 if (verbosemode)
743 printf("Elf64 client\n");
745 if (elfhdrp->e_phnum == 0 || elfhdrp->e_phoff == 0)
746 goto elf64error;
748 entrypt = elfhdrp->e_entry;
749 if (verbosemode)
750 dprintf("Entry point: 0x%llx\n", (u_longlong_t)entrypt);
753 * Allocate and read in all the program headers.
755 nphdrs = elfhdrp->e_phnum;
756 phdrsize = nphdrs * elfhdrp->e_phentsize;
757 allphdrs = kmem_alloc(phdrsize, 0);
758 if (allphdrs == NULL)
759 goto elf64error;
760 if (verbosemode)
761 dprintf("lseek: args = %x %llx %x\n", fd,
762 (u_longlong_t)elfhdrp->e_phoff, 0);
763 if (lseek(fd, elfhdrp->e_phoff, 0) == -1)
764 goto elf64error;
765 if (xread(fd, allphdrs, phdrsize) != phdrsize)
766 goto elf64error;
769 * First look for PT_NOTE headers that tell us what pagesize to
770 * use in allocating program memory.
772 npagesize = 0;
773 for (i = 0; i < nphdrs; i++) {
774 void *note_buf;
776 phdr = (Elf64_Phdr *)(allphdrs + elfhdrp->e_phentsize * i);
777 if (phdr->p_type != PT_NOTE)
778 continue;
779 if (verbosemode) {
780 dprintf("allocating 0x%llx bytes for note hdr\n",
781 (u_longlong_t)phdr->p_filesz);
783 if ((note_buf = kmem_alloc(phdr->p_filesz, 0)) == NULL)
784 goto elf64error;
785 if (verbosemode)
786 dprintf("seeking to 0x%llx\n",
787 (u_longlong_t)phdr->p_offset);
788 if (lseek(fd, phdr->p_offset, 0) == -1)
789 goto elf64error;
790 if (verbosemode) {
791 dprintf("reading 0x%llx bytes into 0x%p\n",
792 (u_longlong_t)phdr->p_filesz, (void *)nhdr);
794 nhdr = (Elf64_Nhdr *)note_buf;
795 if (xread(fd, (caddr_t)nhdr, phdr->p_filesz) != phdr->p_filesz)
796 goto elf64error;
797 if (verbosemode) {
798 dprintf("p_note namesz %x descsz %x type %x\n",
799 nhdr->n_namesz, nhdr->n_descsz, nhdr->n_type);
803 * Iterate through all ELF PT_NOTE elements looking for
804 * ELF_NOTE_SOLARIS which, if present, will specify the
805 * executable's preferred pagesize.
807 do {
808 namep = (caddr_t)(nhdr + 1);
810 if (nhdr->n_namesz == strlen(ELF_NOTE_SOLARIS) + 1 &&
811 strcmp(namep, ELF_NOTE_SOLARIS) == 0 &&
812 nhdr->n_type == ELF_NOTE_PAGESIZE_HINT) {
813 descp = namep + roundup(nhdr->n_namesz, 4);
814 npagesize = *(int *)descp;
815 if (verbosemode)
816 dprintf("pagesize is %x\n", npagesize);
819 offset += sizeof (Elf64_Nhdr) + roundup(nhdr->n_namesz,
820 4) + roundup(nhdr->n_descsz, 4);
822 nhdr = (Elf64_Nhdr *)((char *)note_buf + offset);
823 } while (offset < phdr->p_filesz);
825 kmem_free(note_buf, phdr->p_filesz);
826 nhdr = NULL;
830 * Next look for PT_LOAD headers to read in.
832 if (print)
833 printf("Size: ");
834 for (i = 0; i < nphdrs; i++) {
835 phdr = (Elf64_Phdr *)(allphdrs + elfhdrp->e_phentsize * i);
836 if (verbosemode) {
837 dprintf("Doing header 0x%x\n", i);
838 dprintf("phdr\n");
839 dprintf("\tp_offset = %llx, p_vaddr = %llx\n",
840 (u_longlong_t)phdr->p_offset,
841 (u_longlong_t)phdr->p_vaddr);
842 dprintf("\tp_memsz = %llx, p_filesz = %llx\n",
843 (u_longlong_t)phdr->p_memsz,
844 (u_longlong_t)phdr->p_filesz);
845 dprintf("\tp_type = %x, p_flags = %x\n",
846 phdr->p_type, phdr->p_flags);
848 if (phdr->p_type == PT_LOAD) {
849 if (verbosemode)
850 dprintf("seeking to 0x%llx\n",
851 (u_longlong_t)phdr->p_offset);
852 if (lseek(fd, phdr->p_offset, 0) == -1)
853 goto elf64error;
855 if (phdr->p_flags == (PF_R | PF_W) &&
856 phdr->p_vaddr == 0) {
858 * It's a PT_LOAD segment that is RW but
859 * not executable and has a vaddr
860 * of zero. This is relocation info that
861 * doesn't need to stick around after
862 * krtld is done with it. We allocate boot
863 * memory for this segment, since we don't want
864 * it mapped in permanently as part of
865 * the kernel image.
867 #ifdef BOOTAMD64
868 if ((loadaddr = (Elf64_Addr)
869 (ADDR_XTND(kmem_alloc(phdr->p_memsz, 0))))
870 == NULL)
871 #else /* !BOOTAMD64 */
872 if ((loadaddr = (Elf64_Addr)(uintptr_t)
873 kmem_alloc(phdr->p_memsz, 0)) == NULL)
874 #endif /* BOOTAMD64 */
875 goto elf64error;
878 * Save this to pass on
879 * to the interpreter.
881 phdr->p_vaddr = loadaddr;
882 } else {
883 if (print)
884 printf("0x%llx+",
885 (u_longlong_t)phdr->p_filesz);
887 * If we found a new pagesize above, use it
888 * to adjust the memory allocation.
890 loadaddr = phdr->p_vaddr;
891 if (use_align && npagesize != 0) {
892 off = loadaddr & (npagesize - 1);
893 size = roundup(phdr->p_memsz + off,
894 npagesize);
895 base = loadaddr - off;
896 } else {
897 npagesize = 0;
898 size = phdr->p_memsz;
899 base = loadaddr;
902 * Check if it's text or data.
904 if (phdr->p_flags & PF_W)
905 dhdr = phdr;
906 else
907 thdr = phdr;
909 if (verbosemode)
910 dprintf(
911 "allocating memory: %llx %lx %x\n",
912 (u_longlong_t)base,
913 size, npagesize);
916 * If memory size is zero just ignore this
917 * header.
919 if (size == 0)
920 continue;
923 * We're all set up to read.
924 * Now let's allocate some memory.
926 if (get_progmemory((caddr_t)(uintptr_t)base,
927 size, npagesize))
928 goto elf64error;
931 if (verbosemode) {
932 dprintf("reading 0x%llx bytes into 0x%llx\n",
933 (u_longlong_t)phdr->p_filesz,
934 (u_longlong_t)loadaddr);
936 if (xread(fd, (caddr_t)(uintptr_t)
937 loadaddr, phdr->p_filesz) != phdr->p_filesz)
938 goto elf64error;
940 /* zero out BSS */
941 if (phdr->p_memsz > phdr->p_filesz) {
942 loadaddr += phdr->p_filesz;
943 if (verbosemode) {
944 dprintf("bss from 0x%llx size 0x%llx\n",
945 (u_longlong_t)loadaddr,
946 (u_longlong_t)(phdr->p_memsz -
947 phdr->p_filesz));
950 bzero((caddr_t)(uintptr_t)loadaddr,
951 phdr->p_memsz - phdr->p_filesz);
952 bss_seen++;
953 if (print)
954 printf("0x%llx Bytes\n",
955 (u_longlong_t)(phdr->p_memsz -
956 phdr->p_filesz));
959 /* force instructions to be visible to icache */
960 if (phdr->p_flags & PF_X)
961 sync_instruction_memory((caddr_t)(uintptr_t)
962 phdr->p_vaddr, phdr->p_memsz);
964 } else if (phdr->p_type == PT_INTERP) {
966 * Dynamically-linked executable.
968 interp = 1;
969 if (lseek(fd, phdr->p_offset, 0) == -1) {
970 goto elf64error;
973 * Get the name of the interpreter.
975 if (xread(fd, dlname, phdr->p_filesz) !=
976 phdr->p_filesz ||
977 dlname[phdr->p_filesz - 1] != '\0')
978 goto elf64error;
979 } else if (phdr->p_type == PT_DYNAMIC) {
980 dynamic = phdr->p_vaddr;
984 if (!bss_seen && print)
985 printf("0 Bytes\n");
988 * Load the interpreter
989 * if there is one.
991 if (interp) {
992 Elf64_Boot bootv[EB_MAX]; /* Bootstrap vector */
993 auxv64_t auxv[__BOOT_NAUXV_IMPL]; /* Aux vector */
994 Elf64_Boot *bv = bootv;
995 auxv64_t *av = auxv;
996 size_t vsize;
999 * Load it.
1001 if ((entrypt = iload64(dlname, thdr, dhdr, &av)) ==
1002 FAIL_ILOAD64)
1003 goto elf64error;
1005 * Build bootstrap and aux vectors.
1007 setup_aux();
1008 EBV64(bv, EB_AUXV, 0); /* fill in later */
1009 EBV64(bv, EB_PAGESIZE, pagesize);
1010 EBV64(bv, EB_DYNAMIC, dynamic);
1011 EBV64(bv, EB_NULL, 0);
1013 AUX64(av, AT_BASE, entrypt);
1014 AUX64(av, AT_ENTRY, elfhdrp->e_entry);
1015 AUX64(av, AT_PAGESZ, pagesize);
1016 AUX64(av, AT_PHDR, (uintptr_t)allphdrs);
1017 AUX64(av, AT_PHNUM, elfhdrp->e_phnum);
1018 AUX64(av, AT_PHENT, elfhdrp->e_phentsize);
1019 if (npagesize)
1020 AUX64(av, AT_SUN_LPAGESZ, npagesize);
1022 #ifdef BOOTAMD64
1023 vsize = strlen(amd64_getmmulist()) + 1;
1024 if ((mmulist = kmem_alloc(vsize, 0)) == NULL)
1025 goto elf64error;
1027 bcopy(amd64_getmmulist(), mmulist, vsize);
1028 AUX64(av, AT_SUN_MMU, (uintptr_t)mmulist);
1029 #endif /* BOOTAMD64 */
1031 AUX64(av, AT_SUN_IFLUSH, icache_flush);
1032 if (cpulist != NULL)
1033 AUX64(av, AT_SUN_CPU, (uintptr_t)cpulist);
1034 AUX64(av, AT_NULL, 0);
1036 * Realloc vectors and copy them.
1038 vsize = (caddr_t)bv - (caddr_t)bootv;
1039 if ((elfbootvecELF64 =
1040 (Elf64_Boot *)kmem_alloc(vsize, 0)) == NULL)
1041 goto elf64error;
1042 bcopy((char *)bootv, (char *)elfbootvecELF64, vsize);
1044 size = (caddr_t)av - (caddr_t)auxv;
1045 if (size > sizeof (auxv)) {
1046 printf("readelf: overrun of available aux vectors\n");
1047 kmem_free(elfbootvecELF64, vsize);
1048 goto elf64error;
1051 #ifdef BOOTAMD64
1052 if ((elfbootvecELF64->eb_un.eb_ptr =
1053 ADDR_XTND(kmem_alloc(size, 0))) == NULL) {
1054 kmem_free(elfbootvecELF64, vsize);
1055 goto elf64error;
1058 bcopy((char *)auxv,
1059 (char *)ADDR_TRUNC((elfbootvecELF64->eb_un.eb_ptr)), size);
1060 #else /* !BOOTAMD64 */
1061 if ((elfbootvecELF64->eb_un.eb_ptr =
1062 (Elf64_Addr)kmem_alloc(size, 0)) == NULL) {
1063 kmem_free(elfbootvecELF64, vsize);
1064 goto elf64error;
1067 bcopy((char *)auxv, (char *)(elfbootvecELF64->eb_un.eb_ptr),
1068 size);
1069 #endif /* BOOTAMD64 */
1070 } else {
1071 kmem_free(allphdrs, phdrsize);
1073 return ((uint64_t)entrypt);
1075 elf64error:
1076 if (allphdrs != NULL)
1077 kmem_free(allphdrs, phdrsize);
1078 if (nhdr != NULL)
1079 kmem_free(nhdr, phdr->p_filesz);
1080 printf("Elf64 read error.\n");
1081 return (FAIL_READELF64);
1083 #endif /* _ELF64_SUPPORT */
1086 * Load the interpreter. It expects a
1087 * relocatable .o capable of bootstrapping
1088 * itself.
1090 static func_t
1091 iload32(char *rtld, Elf32_Phdr *thdr, Elf32_Phdr *dhdr, auxv32_t **avp)
1093 Elf32_Ehdr *ehdr = NULL;
1094 uintptr_t dl_entry = 0;
1095 uint_t i;
1096 int fd;
1097 int size;
1098 caddr_t shdrs = NULL;
1099 caddr_t etext, edata;
1101 /* use uintptr_t to suppress the gcc warning */
1102 etext = (caddr_t)(uintptr_t)thdr->p_vaddr + thdr->p_memsz;
1103 edata = (caddr_t)(uintptr_t)dhdr->p_vaddr + dhdr->p_memsz;
1106 * Get the module path.
1108 module_path = getmodpath(filename);
1110 if ((fd = openpath(module_path, rtld, O_RDONLY)) < 0) {
1111 printf("boot: cannot find %s\n", rtld);
1112 goto errorx;
1114 dprintf("Opened %s OK\n", rtld);
1115 AUX(*avp, AT_SUN_LDNAME, rtld);
1117 * Allocate and read the ELF header.
1119 if ((ehdr = (Elf32_Ehdr *)kmem_alloc(sizeof (Elf32_Ehdr), 0)) == NULL) {
1120 printf("boot: alloc error reading ELF header (%s).\n", rtld);
1121 goto error;
1124 if (xread(fd, (char *)ehdr, sizeof (*ehdr)) != sizeof (*ehdr)) {
1125 printf("boot: error reading ELF header (%s).\n", rtld);
1126 goto error;
1129 size = ehdr->e_shentsize * ehdr->e_shnum;
1130 if ((shdrs = kmem_alloc(size, 0)) == NULL) {
1131 printf("boot: alloc error reading ELF header (%s).\n", rtld);
1132 goto error;
1135 * Read the section headers.
1137 if (lseek(fd, ehdr->e_shoff, 0) == -1 ||
1138 xread(fd, shdrs, size) != size) {
1139 printf("boot: error reading section headers\n");
1140 goto error;
1142 AUX(*avp, AT_SUN_LDELF, ehdr);
1143 AUX(*avp, AT_SUN_LDSHDR, shdrs);
1145 * Load sections into the appropriate dynamic segment.
1147 for (i = 1; i < ehdr->e_shnum; i++) {
1148 Elf32_Shdr *sp;
1149 caddr_t *spp;
1150 caddr_t load;
1152 sp = (Elf32_Shdr *)(shdrs + (i*ehdr->e_shentsize));
1154 * If it's not allocated and not required
1155 * to do relocation, skip it.
1157 if (!(sp->sh_flags & SHF_ALLOC) &&
1158 #ifdef i386
1159 sp->sh_type != SHT_REL &&
1160 #else
1161 sp->sh_type != SHT_RELA &&
1162 #endif
1163 sp->sh_type != SHT_SYMTAB &&
1164 sp->sh_type != SHT_STRTAB)
1165 continue;
1167 * If the section is read-only,
1168 * it goes in as text.
1170 spp = (sp->sh_flags & SHF_WRITE)? &edata: &etext;
1172 * Make some room for it.
1174 load = segbrk(spp, sp->sh_size, sp->sh_addralign);
1175 if (load == NULL) {
1176 printf("boot: allocating memory for sections failed\n");
1177 goto error;
1180 * Compute the entry point of the linker.
1182 if (dl_entry == 0 &&
1183 !(sp->sh_flags & SHF_WRITE) &&
1184 (sp->sh_flags & SHF_EXECINSTR)) {
1185 dl_entry = (uintptr_t)load + ehdr->e_entry;
1188 * If it's bss, just zero it out.
1190 if (sp->sh_type == SHT_NOBITS) {
1191 bzero(load, sp->sh_size);
1192 } else {
1194 * Read the section contents.
1196 if (lseek(fd, sp->sh_offset, 0) == -1 ||
1197 xread(fd, load, sp->sh_size) != sp->sh_size) {
1198 printf("boot: error reading sections\n");
1199 goto error;
1203 * Assign the section's virtual addr. Use uintptr_t to
1204 * suppress the gcc warning.
1206 sp->sh_addr = (Elf32_Off)(uintptr_t)load;
1208 * Force instructions to be visible to icache. Use
1209 * uintptr_t to suppress the gcc warning as well.
1211 if (sp->sh_flags & SHF_EXECINSTR)
1212 sync_instruction_memory((caddr_t)(uintptr_t)sp->sh_addr,
1213 sp->sh_size);
1216 * Update sizes of segments.
1218 thdr->p_memsz = (Elf32_Word)((uintptr_t)etext - thdr->p_vaddr);
1219 dhdr->p_memsz = (Elf32_Word)((uintptr_t)edata - dhdr->p_vaddr);
1221 /* load and relocate symbol tables in SAS */
1222 (void) close(fd);
1223 return ((func_t)dl_entry);
1225 error:
1226 (void) close(fd);
1227 errorx:
1228 if (ehdr)
1229 kmem_free(ehdr, sizeof (Elf32_Ehdr));
1230 if (shdrs)
1231 kmem_free(shdrs, size);
1232 printf("boot: error loading interpreter (%s)\n", rtld);
1233 return (FAIL);
1236 #ifdef _ELF64_SUPPORT
1238 * Load the interpreter. It expects a
1239 * relocatable .o capable of bootstrapping
1240 * itself.
1242 static Elf64_Addr
1243 iload64(char *rtld, Elf64_Phdr *thdr, Elf64_Phdr *dhdr, auxv64_t **avp)
1245 Elf64_Ehdr *ehdr = NULL;
1246 Elf64_Addr dl_entry = (Elf64_Addr)0;
1247 Elf64_Addr etext, edata;
1248 uint_t i;
1249 int fd;
1250 int size;
1251 caddr_t shdrs = NULL;
1253 etext = thdr->p_vaddr + thdr->p_memsz;
1254 edata = dhdr->p_vaddr + dhdr->p_memsz;
1257 * Get the module path.
1259 module_path = getmodpath(filename);
1261 if ((fd = openpath(module_path, rtld, O_RDONLY)) < 0) {
1262 printf("boot: cannot find %s\n", rtld);
1263 goto errorx;
1265 dprintf("Opened %s OK\n", rtld);
1266 AUX64(*avp, AT_SUN_LDNAME, (uintptr_t)rtld);
1268 * Allocate and read the ELF header.
1270 #ifdef BOOTAMD64
1271 if ((ehdr = (Elf64_Ehdr *)(uintptr_t)kmem_alloc(sizeof (Elf64_Ehdr),
1272 0)) == NULL) {
1273 #else /* !BOOTAMD64 */
1274 if ((ehdr = (Elf64_Ehdr *)kmem_alloc(sizeof (Elf64_Ehdr), 0)) == NULL) {
1275 #endif /* BOOTAMD64 */
1276 printf("boot: alloc error reading ELF header (%s).\n", rtld);
1277 goto error;
1280 if (xread(fd, (char *)ehdr, sizeof (*ehdr)) != sizeof (*ehdr)) {
1281 printf("boot: error reading ELF header (%s).\n", rtld);
1282 goto error;
1285 size = ehdr->e_shentsize * ehdr->e_shnum;
1286 if ((shdrs = kmem_alloc(size, 0)) == NULL) {
1287 printf("boot: alloc error reading ELF header (%s).\n", rtld);
1288 goto error;
1291 * Read the section headers.
1293 if (lseek(fd, ehdr->e_shoff, 0) == -1 ||
1294 xread(fd, shdrs, size) != size) {
1295 printf("boot: error reading section headers\n");
1296 goto error;
1299 #ifdef BOOTAMD64
1300 AUX64(*avp, AT_SUN_LDELF, (uintptr_t)ehdr);
1301 AUX64(*avp, AT_SUN_LDSHDR, (uintptr_t)shdrs);
1302 #else /* !BOOTAMD64 */
1303 AUX64(*avp, AT_SUN_LDELF, ehdr);
1304 AUX64(*avp, AT_SUN_LDSHDR, shdrs);
1305 #endif /* BOOTAMD64 */
1308 * Load sections into the appropriate dynamic segment.
1310 for (i = 1; i < ehdr->e_shnum; i++) {
1311 Elf64_Shdr *sp;
1312 Elf64_Addr *spp, load;
1314 sp = (Elf64_Shdr *)(shdrs + (i*ehdr->e_shentsize));
1316 * If it's not allocated and not required
1317 * to do relocation, skip it.
1319 if (!(sp->sh_flags & SHF_ALLOC) &&
1320 sp->sh_type != SHT_SYMTAB &&
1321 sp->sh_type != SHT_STRTAB &&
1322 sp->sh_type != SHT_RELA)
1323 continue;
1325 * If the section is read-only,
1326 * it goes in as text.
1328 spp = (sp->sh_flags & SHF_WRITE)? &edata: &etext;
1331 * Make some room for it.
1333 #ifdef BOOTAMD64
1334 load = ADDR_XTND(segbrk((caddr_t *)spp,
1335 sp->sh_size, sp->sh_addralign));
1336 #else /* !BOOTAMD64 */
1337 load = (Elf64_Addr)segbrk((caddr_t *)spp, sp->sh_size,
1338 sp->sh_addralign);
1339 #endif /* BOOTAMD64 */
1341 if (load == NULL) {
1342 printf("boot: allocating memory for section %d "
1343 "failed\n", i);
1344 goto error;
1348 * Compute the entry point of the linker.
1350 if (dl_entry == 0 &&
1351 !(sp->sh_flags & SHF_WRITE) &&
1352 (sp->sh_flags & SHF_EXECINSTR)) {
1353 dl_entry = load + ehdr->e_entry;
1354 if (verbosemode)
1355 dprintf("boot: loading linker @ 0x%llx\n",
1356 (u_longlong_t)dl_entry);
1360 * If it's bss, just zero it out.
1362 if (sp->sh_type == SHT_NOBITS) {
1363 bzero((caddr_t)(uintptr_t)load, sp->sh_size);
1364 } else {
1366 * Read the section contents.
1368 if (lseek(fd, sp->sh_offset, 0) == -1 ||
1369 xread(fd, (caddr_t)(uintptr_t)load, sp->sh_size) !=
1370 sp->sh_size) {
1371 printf("boot: error reading section %d\n", i);
1372 goto error;
1376 * Assign the section's virtual addr.
1379 sp->sh_addr = load;
1381 if (verbosemode)
1382 dprintf("boot: section %d, type %d, loaded @ 0x%llx, "
1383 "size 0x%llx\n", i, sp->sh_type, (u_longlong_t)load,
1384 (u_longlong_t)sp->sh_size);
1386 /* force instructions to be visible to icache */
1387 if (sp->sh_flags & SHF_EXECINSTR)
1388 sync_instruction_memory((caddr_t)(uintptr_t)sp->sh_addr,
1389 sp->sh_size);
1392 * Update sizes of segments.
1394 thdr->p_memsz = etext - thdr->p_vaddr;
1395 dhdr->p_memsz = edata - dhdr->p_vaddr;
1397 /* load and relocate symbol tables in SAS */
1398 (void) close(fd);
1399 return (dl_entry);
1401 error:
1402 (void) close(fd);
1403 errorx:
1404 if (ehdr)
1405 kmem_free((caddr_t)ehdr, sizeof (Elf64_Ehdr));
1406 if (shdrs)
1407 kmem_free(shdrs, size);
1408 printf("boot: error loading interpreter (%s)\n", rtld);
1409 return (FAIL_ILOAD64);
1411 #endif /* _ELF64_SUPPORT */
1414 * Extend the segment's "break" value by bytes.
1416 static caddr_t
1417 segbrk(caddr_t *spp, size_t bytes, size_t align)
1419 caddr_t va, pva;
1420 size_t size = 0;
1421 unsigned int alloc_pagesize = pagesize;
1422 unsigned int alloc_align = 0;
1424 if (npagesize) {
1425 alloc_align = npagesize;
1426 alloc_pagesize = npagesize;
1429 va = (caddr_t)ALIGN(*spp, align);
1430 pva = (caddr_t)roundup((uintptr_t)*spp, alloc_pagesize);
1432 * Need more pages?
1434 if (va + bytes > pva) {
1435 size = roundup((bytes - (pva - va)), alloc_pagesize);
1437 if (get_progmemory(pva, size, alloc_align)) {
1438 printf("boot: segbrk allocation failed, "
1439 "0x%lx bytes @ %p\n", bytes, (void *)pva);
1440 return (NULL);
1443 *spp = va + bytes;
1445 return (va);
1449 * Open the file using a search path and
1450 * return the file descriptor (or -1 on failure).
1452 static int
1453 openpath(path, fname, flags)
1454 char *path;
1455 char *fname;
1456 int flags;
1458 register char *p, *q;
1459 char buf[MAXPATHLEN];
1460 int fd;
1463 * If the file name is absolute,
1464 * don't use the module search path.
1466 if (fname[0] == '/')
1467 return (open(fname, flags));
1469 q = NULL;
1470 for (p = path; /* forever */; p = q) {
1472 while (*p == ' ' || *p == '\t' || *p == ':')
1473 p++;
1474 if (*p == '\0')
1475 break;
1476 q = p;
1477 while (*q && *q != ' ' && *q != '\t' && *q != ':')
1478 q++;
1479 (void) strncpy(buf, p, q - p);
1480 if (q[-1] != '/') {
1481 buf[q - p] = '/';
1482 (void) strcpy(&buf[q - p + 1], fname);
1483 } else {
1485 * This checks for paths that end in '/'
1487 (void) strcpy(&buf[q - p], fname);
1490 if ((fd = open(buf, flags)) > 0)
1491 return (fd);
1493 return (-1);
1497 * Get the module search path.
1499 static char *
1500 getmodpath(fname)
1501 char *fname;
1503 register char *p = strrchr(fname, '/');
1504 static char mod_path[MOD_MAXPATH];
1505 size_t len;
1506 extern char *impl_arch_name;
1507 #if defined(__sparcv9) || defined(BOOTAMD64)
1508 #ifdef __sparcv9
1509 char *isastr = "/sparcv9";
1510 #endif /* __sparcv9 */
1511 #ifdef BOOTAMD64
1512 char *isastr = "/amd64";
1513 #endif /* BOOTAMD64 */
1514 size_t isalen = strlen(isastr);
1515 #endif /* __sparcv9 || BOOTAMD64 */
1517 if (p == NULL) {
1518 /* strchr could not find a "/" */
1519 printf("%s is not a legal kernel pathname", fname);
1520 return (NULL);
1522 while (p > fname && *(p - 1) == '/')
1523 p--; /* remove trailing "/"s */
1524 if (p == fname)
1525 p++; /* "/" is the modpath in this case */
1527 len = p - fname;
1528 (void) strncpy(mod_path, fname, len);
1529 mod_path[len] = 0;
1531 #if defined(__sparcv9) || defined(BOOTAMD64)
1532 len = strlen(mod_path);
1533 if ((len > isalen) && (strcmp(&mod_path[len - isalen], isastr) == 0)) {
1534 mod_path[len - isalen] = '\0';
1535 #if defined(__sparcv9)
1536 if ((client_isLP64 == 0) && verbosemode)
1537 printf("Assuming LP64 %s client.\n", isastr);
1538 client_isLP64 = 1;
1539 #endif /* __sparcv9 */
1541 #endif /* __sparcv9 || BOOTAMD64 */
1542 mod_path_uname_m(mod_path, impl_arch_name);
1543 (void) strcat(mod_path, " ");
1544 (void) strcat(mod_path, MOD_DEFPATH);
1546 if (boothowto & RB_ASKNAME) {
1547 char buf[MOD_MAXPATH];
1549 printf("Enter default directory for modules [%s]: ", mod_path);
1550 (void) cons_gets(buf, sizeof (buf));
1551 if (buf[0] != '\0')
1552 (void) strcpy(mod_path, buf);
1554 if (verbosemode)
1555 printf("modpath: %s\n", mod_path);
1556 return (mod_path);