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