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 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 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 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 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 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 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 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 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 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 * 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