diff options
| -rw-r--r-- | arch/arc/kernel/head.S | 4 | ||||
| -rw-r--r-- | arch/arc/kernel/setup.c | 87 |
2 files changed, 64 insertions, 27 deletions
diff --git a/arch/arc/kernel/head.S b/arch/arc/kernel/head.S index 26e33a8b2d18..1f945d0f40da 100644 --- a/arch/arc/kernel/head.S +++ b/arch/arc/kernel/head.S | |||
| @@ -103,9 +103,9 @@ ENTRY(stext) | |||
| 103 | #ifdef CONFIG_ARC_UBOOT_SUPPORT | 103 | #ifdef CONFIG_ARC_UBOOT_SUPPORT |
| 104 | ; Uboot - kernel ABI | 104 | ; Uboot - kernel ABI |
| 105 | ; r0 = [0] No uboot interaction, [1] cmdline in r2, [2] DTB in r2 | 105 | ; r0 = [0] No uboot interaction, [1] cmdline in r2, [2] DTB in r2 |
| 106 | ; r1 = magic number (board identity, unused as of now | 106 | ; r1 = magic number (always zero as of now) |
| 107 | ; r2 = pointer to uboot provided cmdline or external DTB in mem | 107 | ; r2 = pointer to uboot provided cmdline or external DTB in mem |
| 108 | ; These are handled later in setup_arch() | 108 | ; These are handled later in handle_uboot_args() |
| 109 | st r0, [@uboot_tag] | 109 | st r0, [@uboot_tag] |
| 110 | st r2, [@uboot_arg] | 110 | st r2, [@uboot_arg] |
| 111 | #endif | 111 | #endif |
diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c index def19b0ef8c6..8bb156164556 100644 --- a/arch/arc/kernel/setup.c +++ b/arch/arc/kernel/setup.c | |||
| @@ -462,43 +462,80 @@ void setup_processor(void) | |||
| 462 | arc_chk_core_config(); | 462 | arc_chk_core_config(); |
| 463 | } | 463 | } |
| 464 | 464 | ||
| 465 | static inline int is_kernel(unsigned long addr) | 465 | static inline bool uboot_arg_invalid(unsigned long addr) |
| 466 | { | 466 | { |
| 467 | if (addr >= (unsigned long)_stext && addr <= (unsigned long)_end) | 467 | /* |
| 468 | return 1; | 468 | * Check that it is a untranslated address (although MMU is not enabled |
| 469 | return 0; | 469 | * yet, it being a high address ensures this is not by fluke) |
| 470 | */ | ||
| 471 | if (addr < PAGE_OFFSET) | ||
| 472 | return true; | ||
| 473 | |||
| 474 | /* Check that address doesn't clobber resident kernel image */ | ||
| 475 | return addr >= (unsigned long)_stext && addr <= (unsigned long)_end; | ||
| 470 | } | 476 | } |
| 471 | 477 | ||
| 472 | void __init setup_arch(char **cmdline_p) | 478 | #define IGNORE_ARGS "Ignore U-boot args: " |
| 479 | |||
| 480 | /* uboot_tag values for U-boot - kernel ABI revision 0; see head.S */ | ||
| 481 | #define UBOOT_TAG_NONE 0 | ||
| 482 | #define UBOOT_TAG_CMDLINE 1 | ||
| 483 | #define UBOOT_TAG_DTB 2 | ||
| 484 | |||
| 485 | void __init handle_uboot_args(void) | ||
| 473 | { | 486 | { |
| 487 | bool use_embedded_dtb = true; | ||
| 488 | bool append_cmdline = false; | ||
| 489 | |||
| 474 | #ifdef CONFIG_ARC_UBOOT_SUPPORT | 490 | #ifdef CONFIG_ARC_UBOOT_SUPPORT |
| 475 | /* make sure that uboot passed pointer to cmdline/dtb is valid */ | 491 | /* check that we know this tag */ |
| 476 | if (uboot_tag && is_kernel((unsigned long)uboot_arg)) | 492 | if (uboot_tag != UBOOT_TAG_NONE && |
| 477 | panic("Invalid uboot arg\n"); | 493 | uboot_tag != UBOOT_TAG_CMDLINE && |
| 494 | uboot_tag != UBOOT_TAG_DTB) { | ||
| 495 | pr_warn(IGNORE_ARGS "invalid uboot tag: '%08x'\n", uboot_tag); | ||
| 496 | goto ignore_uboot_args; | ||
| 497 | } | ||
| 498 | |||
| 499 | if (uboot_tag != UBOOT_TAG_NONE && | ||
| 500 | uboot_arg_invalid((unsigned long)uboot_arg)) { | ||
| 501 | pr_warn(IGNORE_ARGS "invalid uboot arg: '%px'\n", uboot_arg); | ||
| 502 | goto ignore_uboot_args; | ||
| 503 | } | ||
| 504 | |||
| 505 | /* see if U-boot passed an external Device Tree blob */ | ||
| 506 | if (uboot_tag == UBOOT_TAG_DTB) { | ||
| 507 | machine_desc = setup_machine_fdt((void *)uboot_arg); | ||
| 478 | 508 | ||
| 479 | /* See if u-boot passed an external Device Tree blob */ | 509 | /* external Device Tree blob is invalid - use embedded one */ |
| 480 | machine_desc = setup_machine_fdt(uboot_arg); /* uboot_tag == 2 */ | 510 | use_embedded_dtb = !machine_desc; |
| 481 | if (!machine_desc) | 511 | } |
| 512 | |||
| 513 | if (uboot_tag == UBOOT_TAG_CMDLINE) | ||
| 514 | append_cmdline = true; | ||
| 515 | |||
| 516 | ignore_uboot_args: | ||
| 482 | #endif | 517 | #endif |
| 483 | { | 518 | |
| 484 | /* No, so try the embedded one */ | 519 | if (use_embedded_dtb) { |
| 485 | machine_desc = setup_machine_fdt(__dtb_start); | 520 | machine_desc = setup_machine_fdt(__dtb_start); |
| 486 | if (!machine_desc) | 521 | if (!machine_desc) |
| 487 | panic("Embedded DT invalid\n"); | 522 | panic("Embedded DT invalid\n"); |
| 523 | } | ||
| 488 | 524 | ||
| 489 | /* | 525 | /* |
| 490 | * If we are here, it is established that @uboot_arg didn't | 526 | * NOTE: @boot_command_line is populated by setup_machine_fdt() so this |
| 491 | * point to DT blob. Instead if u-boot says it is cmdline, | 527 | * append processing can only happen after. |
| 492 | * append to embedded DT cmdline. | 528 | */ |
| 493 | * setup_machine_fdt() would have populated @boot_command_line | 529 | if (append_cmdline) { |
| 494 | */ | 530 | /* Ensure a whitespace between the 2 cmdlines */ |
| 495 | if (uboot_tag == 1) { | 531 | strlcat(boot_command_line, " ", COMMAND_LINE_SIZE); |
| 496 | /* Ensure a whitespace between the 2 cmdlines */ | 532 | strlcat(boot_command_line, uboot_arg, COMMAND_LINE_SIZE); |
| 497 | strlcat(boot_command_line, " ", COMMAND_LINE_SIZE); | ||
| 498 | strlcat(boot_command_line, uboot_arg, | ||
| 499 | COMMAND_LINE_SIZE); | ||
| 500 | } | ||
| 501 | } | 533 | } |
| 534 | } | ||
| 535 | |||
| 536 | void __init setup_arch(char **cmdline_p) | ||
| 537 | { | ||
| 538 | handle_uboot_args(); | ||
| 502 | 539 | ||
| 503 | /* Save unparsed command line copy for /proc/cmdline */ | 540 | /* Save unparsed command line copy for /proc/cmdline */ |
| 504 | *cmdline_p = boot_command_line; | 541 | *cmdline_p = boot_command_line; |
