1 /*- 2 * Copyright (c) 2004 Olivier Houchard 3 * Copyright (c) 1994-1998 Mark Brinicombe. 4 * Copyright (c) 1994 Brini. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include "opt_platform.h" 30 #include "opt_ddb.h" 31 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <sys/ctype.h> 35 #include <sys/linker.h> 36 #include <sys/physmem.h> 37 #include <sys/reboot.h> 38 #include <sys/sysctl.h> 39 #if defined(LINUX_BOOT_ABI) 40 #include <sys/boot.h> 41 #endif 42 43 #include <machine/atags.h> 44 #include <machine/cpu.h> 45 #include <machine/machdep.h> 46 #include <machine/metadata.h> 47 #include <machine/vmparam.h> /* For KERNVIRTADDR */ 48 49 #ifdef FDT 50 #include <contrib/libfdt/libfdt.h> 51 #include <dev/fdt/fdt_common.h> 52 #endif 53 54 #ifdef EFI 55 #include <sys/efi.h> 56 #endif 57 58 #ifdef DDB 59 #include <ddb/ddb.h> 60 #endif 61 62 #ifdef DEBUG 63 #define debugf(fmt, args...) printf(fmt, ##args) 64 #else 65 #define debugf(fmt, args...) 66 #endif 67 68 #ifdef LINUX_BOOT_ABI 69 static char static_kenv[4096]; 70 #endif 71 72 extern int *end; 73 74 static uint32_t board_revision; 75 /* hex representation of uint64_t */ 76 static char board_serial[32]; 77 static char *loader_envp; 78 79 #if defined(LINUX_BOOT_ABI) 80 #define LBABI_MAX_BANKS 10 81 #define CMDLINE_GUARD "FreeBSD:" 82 static uint32_t board_id; 83 static struct arm_lbabi_tag *atag_list; 84 static char linux_command_line[LBABI_MAX_COMMAND_LINE + 1]; 85 static char atags[LBABI_MAX_COMMAND_LINE * 2]; 86 #endif /* defined(LINUX_BOOT_ABI) */ 87 88 SYSCTL_NODE(_hw, OID_AUTO, board, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, 89 "Board attributes"); 90 SYSCTL_UINT(_hw_board, OID_AUTO, revision, CTLFLAG_RD, 91 &board_revision, 0, "Board revision"); 92 SYSCTL_STRING(_hw_board, OID_AUTO, serial, CTLFLAG_RD, 93 board_serial, 0, "Board serial"); 94 95 int vfp_exists; 96 SYSCTL_INT(_hw, HW_FLOATINGPT, floatingpoint, CTLFLAG_RD, 97 &vfp_exists, 0, "Floating point support enabled"); 98 99 void 100 board_set_serial(uint64_t serial) 101 { 102 103 snprintf(board_serial, sizeof(board_serial)-1, 104 "%016jx", serial); 105 } 106 107 void 108 board_set_revision(uint32_t revision) 109 { 110 111 board_revision = revision; 112 } 113 114 static char * 115 kenv_next(char *cp) 116 { 117 118 if (cp != NULL) { 119 while (*cp != 0) 120 cp++; 121 cp++; 122 if (*cp == 0) 123 cp = NULL; 124 } 125 return (cp); 126 } 127 128 void 129 arm_print_kenv(void) 130 { 131 char *cp; 132 133 debugf("loader passed (static) kenv:\n"); 134 if (loader_envp == NULL) { 135 debugf(" no env, null ptr\n"); 136 return; 137 } 138 debugf(" loader_envp = 0x%08x\n", (uint32_t)loader_envp); 139 140 for (cp = loader_envp; cp != NULL; cp = kenv_next(cp)) 141 debugf(" %x %s\n", (uint32_t)cp, cp); 142 } 143 144 #if defined(LINUX_BOOT_ABI) 145 146 /* Convert the U-Boot command line into FreeBSD kenv and boot options. */ 147 static void 148 cmdline_set_env(char *cmdline, const char *guard) 149 { 150 size_t guard_len; 151 152 /* Skip leading spaces. */ 153 while (isspace(*cmdline)) 154 cmdline++; 155 156 /* Test and remove guard. */ 157 if (guard != NULL && guard[0] != '\0') { 158 guard_len = strlen(guard); 159 if (strncasecmp(cmdline, guard, guard_len) != 0) 160 return; 161 cmdline += guard_len; 162 } 163 164 boothowto |= boot_parse_cmdline(cmdline); 165 } 166 167 /* 168 * Called for armv6 and newer. 169 */ 170 void arm_parse_fdt_bootargs(void) 171 { 172 173 #ifdef FDT 174 if (loader_envp == NULL && fdt_get_chosen_bootargs(linux_command_line, 175 LBABI_MAX_COMMAND_LINE) == 0) { 176 init_static_kenv(static_kenv, sizeof(static_kenv)); 177 cmdline_set_env(linux_command_line, CMDLINE_GUARD); 178 } 179 #endif 180 } 181 182 /* 183 * Called for armv[45]. 184 */ 185 static vm_offset_t 186 linux_parse_boot_param(struct arm_boot_params *abp) 187 { 188 struct arm_lbabi_tag *walker; 189 uint32_t revision; 190 uint64_t serial; 191 int size; 192 vm_offset_t lastaddr; 193 #ifdef FDT 194 struct fdt_header *dtb_ptr; 195 uint32_t dtb_size; 196 #endif 197 198 /* 199 * Linux boot ABI: r0 = 0, r1 is the board type (!= 0) and r2 200 * is atags or dtb pointer. If all of these aren't satisfied, 201 * then punt. Unfortunately, it looks like DT enabled kernels 202 * doesn't uses board type and U-Boot delivers 0 in r1 for them. 203 */ 204 if (abp->abp_r0 != 0 || abp->abp_r2 == 0) 205 return (0); 206 #ifdef FDT 207 /* Test if r2 point to valid DTB. */ 208 dtb_ptr = (struct fdt_header *)abp->abp_r2; 209 if (fdt_check_header(dtb_ptr) == 0) { 210 dtb_size = fdt_totalsize(dtb_ptr); 211 return (fake_preload_metadata(abp, dtb_ptr, dtb_size)); 212 } 213 #endif 214 215 board_id = abp->abp_r1; 216 walker = (struct arm_lbabi_tag *)abp->abp_r2; 217 218 if (ATAG_TAG(walker) != ATAG_CORE) 219 return 0; 220 221 atag_list = walker; 222 while (ATAG_TAG(walker) != ATAG_NONE) { 223 switch (ATAG_TAG(walker)) { 224 case ATAG_CORE: 225 break; 226 case ATAG_MEM: 227 physmem_hardware_region(walker->u.tag_mem.start, 228 walker->u.tag_mem.size); 229 break; 230 case ATAG_INITRD2: 231 break; 232 case ATAG_SERIAL: 233 serial = walker->u.tag_sn.high; 234 serial <<= 32; 235 serial |= walker->u.tag_sn.low; 236 board_set_serial(serial); 237 break; 238 case ATAG_REVISION: 239 revision = walker->u.tag_rev.rev; 240 board_set_revision(revision); 241 break; 242 case ATAG_CMDLINE: 243 size = ATAG_SIZE(walker) - 244 sizeof(struct arm_lbabi_header); 245 size = min(size, LBABI_MAX_COMMAND_LINE); 246 strncpy(linux_command_line, walker->u.tag_cmd.command, 247 size); 248 linux_command_line[size] = '\0'; 249 break; 250 default: 251 break; 252 } 253 walker = ATAG_NEXT(walker); 254 } 255 256 /* Save a copy for later */ 257 bcopy(atag_list, atags, 258 (char *)walker - (char *)atag_list + ATAG_SIZE(walker)); 259 260 lastaddr = fake_preload_metadata(abp, NULL, 0); 261 init_static_kenv(static_kenv, sizeof(static_kenv)); 262 cmdline_set_env(linux_command_line, CMDLINE_GUARD); 263 return lastaddr; 264 } 265 #endif 266 267 #if defined(FREEBSD_BOOT_LOADER) 268 static vm_offset_t 269 freebsd_parse_boot_param(struct arm_boot_params *abp) 270 { 271 vm_offset_t lastaddr = 0; 272 void *mdp; 273 #ifdef DDB 274 vm_offset_t ksym_start; 275 vm_offset_t ksym_end; 276 #endif 277 278 /* 279 * Mask metadata pointer: it is supposed to be on page boundary. If 280 * the first argument (mdp) doesn't point to a valid address the 281 * bootloader must have passed us something else than the metadata 282 * ptr, so we give up. Also give up if we cannot find metadta section 283 * the loader creates that we get all this data out of. 284 */ 285 286 if ((mdp = (void *)(abp->abp_r0 & ~PAGE_MASK)) == NULL) 287 return 0; 288 preload_metadata = mdp; 289 290 /* Initialize preload_kmdp */ 291 preload_initkmdp(false); 292 if (preload_kmdp == NULL) 293 return 0; 294 295 boothowto = MD_FETCH(preload_kmdp, MODINFOMD_HOWTO, int); 296 loader_envp = MD_FETCH(preload_kmdp, MODINFOMD_ENVP, char *); 297 init_static_kenv(loader_envp, 0); 298 lastaddr = MD_FETCH(preload_kmdp, MODINFOMD_KERNEND, vm_offset_t); 299 #ifdef DDB 300 ksym_start = MD_FETCH(preload_kmdp, MODINFOMD_SSYM, uintptr_t); 301 ksym_end = MD_FETCH(preload_kmdp, MODINFOMD_ESYM, uintptr_t); 302 db_fetch_ksymtab(ksym_start, ksym_end, 0); 303 #endif 304 return lastaddr; 305 } 306 #endif 307 308 vm_offset_t 309 default_parse_boot_param(struct arm_boot_params *abp) 310 { 311 vm_offset_t lastaddr; 312 313 #if defined(LINUX_BOOT_ABI) 314 if ((lastaddr = linux_parse_boot_param(abp)) != 0) 315 return lastaddr; 316 #endif 317 #if defined(FREEBSD_BOOT_LOADER) 318 if ((lastaddr = freebsd_parse_boot_param(abp)) != 0) 319 return lastaddr; 320 #endif 321 /* Fall back to hardcoded metadata. */ 322 lastaddr = fake_preload_metadata(abp, NULL, 0); 323 324 return lastaddr; 325 } 326 327 /* 328 * Stub version of the boot parameter parsing routine. We are 329 * called early in initarm, before even VM has been initialized. 330 * This routine needs to preserve any data that the boot loader 331 * has passed in before the kernel starts to grow past the end 332 * of the BSS, traditionally the place boot-loaders put this data. 333 * 334 * Since this is called so early, things that depend on the vm system 335 * being setup (including access to some SoC's serial ports), about 336 * all that can be done in this routine is to copy the arguments. 337 * 338 * This is the default boot parameter parsing routine. Individual 339 * kernels/boards can override this weak function with one of their 340 * own. We just fake metadata... 341 */ 342 __weak_reference(default_parse_boot_param, parse_boot_param); 343 344 /* 345 * Fake up a boot descriptor table 346 */ 347 vm_offset_t 348 fake_preload_metadata(struct arm_boot_params *abp __unused, void *dtb_ptr, 349 size_t dtb_size) 350 { 351 vm_offset_t lastaddr; 352 int i = 0; 353 static uint32_t fake_preload[35]; 354 355 lastaddr = (vm_offset_t)&end; 356 357 fake_preload[i++] = MODINFO_NAME; 358 fake_preload[i++] = strlen("kernel") + 1; 359 strcpy((char *)&fake_preload[i++], "kernel"); 360 i += 1; 361 fake_preload[i++] = MODINFO_TYPE; 362 fake_preload[i++] = strlen(preload_kerntype) + 1; 363 strcpy((char *)&fake_preload[i], preload_kerntype); 364 i += howmany(fake_preload[i - 1], sizeof(uint32_t)); 365 fake_preload[i++] = MODINFO_ADDR; 366 fake_preload[i++] = sizeof(vm_offset_t); 367 fake_preload[i++] = KERNVIRTADDR; 368 fake_preload[i++] = MODINFO_SIZE; 369 fake_preload[i++] = sizeof(uint32_t); 370 fake_preload[i++] = (uint32_t)&end - KERNVIRTADDR; 371 if (dtb_ptr != NULL) { 372 /* Copy DTB to KVA space and insert it into module chain. */ 373 lastaddr = roundup(lastaddr, sizeof(int)); 374 fake_preload[i++] = MODINFO_METADATA | MODINFOMD_DTBP; 375 fake_preload[i++] = sizeof(uint32_t); 376 fake_preload[i++] = (uint32_t)lastaddr; 377 memmove((void *)lastaddr, dtb_ptr, dtb_size); 378 lastaddr += dtb_size; 379 lastaddr = roundup(lastaddr, sizeof(int)); 380 } 381 fake_preload[i++] = 0; 382 fake_preload[i] = 0; 383 preload_metadata = (void *)fake_preload; 384 385 /* Initialize preload_kmdp */ 386 preload_initkmdp(true); 387 388 init_static_kenv(NULL, 0); 389 390 return (lastaddr); 391 } 392 393 #ifdef EFI 394 void 395 arm_add_efi_map_entries(struct efi_map_header *efihdr, struct mem_region *mr, 396 int *mrcnt) 397 { 398 struct efi_md *map, *p; 399 const char *type; 400 size_t efisz; 401 int ndesc, i, j; 402 403 static const char *types[] = { 404 "Reserved", 405 "LoaderCode", 406 "LoaderData", 407 "BootServicesCode", 408 "BootServicesData", 409 "RuntimeServicesCode", 410 "RuntimeServicesData", 411 "ConventionalMemory", 412 "UnusableMemory", 413 "ACPIReclaimMemory", 414 "ACPIMemoryNVS", 415 "MemoryMappedIO", 416 "MemoryMappedIOPortSpace", 417 "PalCode", 418 "PersistentMemory" 419 }; 420 421 *mrcnt = 0; 422 423 /* 424 * Memory map data provided by UEFI via the GetMemoryMap 425 * Boot Services API. 426 */ 427 efisz = roundup2(sizeof(struct efi_map_header), 0x10); 428 map = (struct efi_md *)((uint8_t *)efihdr + efisz); 429 430 if (efihdr->descriptor_size == 0) 431 return; 432 ndesc = efihdr->memory_size / efihdr->descriptor_size; 433 434 if (boothowto & RB_VERBOSE) 435 printf("%23s %12s %12s %8s %4s\n", 436 "Type", "Physical", "Virtual", "#Pages", "Attr"); 437 438 for (i = 0, j = 0, p = map; i < ndesc; i++, 439 p = efi_next_descriptor(p, efihdr->descriptor_size)) { 440 if (boothowto & RB_VERBOSE) { 441 if (p->md_type < nitems(types)) 442 type = types[p->md_type]; 443 else 444 type = "<INVALID>"; 445 printf("%23s %012llx %012llx %08llx ", type, p->md_phys, 446 p->md_virt, p->md_pages); 447 if (p->md_attr & EFI_MD_ATTR_UC) 448 printf("UC "); 449 if (p->md_attr & EFI_MD_ATTR_WC) 450 printf("WC "); 451 if (p->md_attr & EFI_MD_ATTR_WT) 452 printf("WT "); 453 if (p->md_attr & EFI_MD_ATTR_WB) 454 printf("WB "); 455 if (p->md_attr & EFI_MD_ATTR_UCE) 456 printf("UCE "); 457 if (p->md_attr & EFI_MD_ATTR_WP) 458 printf("WP "); 459 if (p->md_attr & EFI_MD_ATTR_RP) 460 printf("RP "); 461 if (p->md_attr & EFI_MD_ATTR_XP) 462 printf("XP "); 463 if (p->md_attr & EFI_MD_ATTR_NV) 464 printf("NV "); 465 if (p->md_attr & EFI_MD_ATTR_MORE_RELIABLE) 466 printf("MORE_RELIABLE "); 467 if (p->md_attr & EFI_MD_ATTR_RO) 468 printf("RO "); 469 if (p->md_attr & EFI_MD_ATTR_RT) 470 printf("RUNTIME"); 471 printf("\n"); 472 } 473 474 switch (p->md_type) { 475 case EFI_MD_TYPE_CODE: 476 case EFI_MD_TYPE_DATA: 477 case EFI_MD_TYPE_BS_CODE: 478 case EFI_MD_TYPE_BS_DATA: 479 case EFI_MD_TYPE_FREE: 480 /* 481 * We're allowed to use any entry with these types. 482 */ 483 break; 484 default: 485 continue; 486 } 487 488 j++; 489 if (j >= FDT_MEM_REGIONS) 490 break; 491 492 mr[j].mr_start = p->md_phys; 493 mr[j].mr_size = p->md_pages * EFI_PAGE_SIZE; 494 } 495 496 *mrcnt = j; 497 } 498 #endif /* EFI */ 499