ARC: U-boot: check arguments paranoidly
Handle U-boot arguments paranoidly: * don't allow to pass unknown tag. * try to use external device tree blob only if corresponding tag (TAG_DTB) is set. * don't check uboot_tag if kernel build with no ARC_UBOOT_SUPPORT. NOTE: If U-boot args are invalid we skip them and try to use embedded device tree blob. We can't panic on invalid U-boot args as we really pass invalid args due to bug in U-boot code. This happens if we don't provide external DTB to U-boot and don't set 'bootargs' U-boot environment variable (which is default case at least for HSDK board) In that case we will pass {r0 = 1 (bootargs in r2); r1 = 0; r2 = 0;} to linux which is invalid. While I'm at it refactor U-boot arguments handling code. Cc: stable@vger.kernel.org Tested-by: Corentin LABBE <clabbe@baylibre.com> Signed-off-by: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com> Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
This commit is contained in:
parent
e494239a00
commit
a66f2e57bd
@ -103,9 +103,9 @@ ENTRY(stext)
|
|||||||
#ifdef CONFIG_ARC_UBOOT_SUPPORT
|
#ifdef CONFIG_ARC_UBOOT_SUPPORT
|
||||||
; Uboot - kernel ABI
|
; Uboot - kernel ABI
|
||||||
; r0 = [0] No uboot interaction, [1] cmdline in r2, [2] DTB in r2
|
; r0 = [0] No uboot interaction, [1] cmdline in r2, [2] DTB in r2
|
||||||
; r1 = magic number (board identity, unused as of now
|
; r1 = magic number (always zero as of now)
|
||||||
; r2 = pointer to uboot provided cmdline or external DTB in mem
|
; r2 = pointer to uboot provided cmdline or external DTB in mem
|
||||||
; These are handled later in setup_arch()
|
; These are handled later in handle_uboot_args()
|
||||||
st r0, [@uboot_tag]
|
st r0, [@uboot_tag]
|
||||||
st r2, [@uboot_arg]
|
st r2, [@uboot_arg]
|
||||||
#endif
|
#endif
|
||||||
|
@ -462,43 +462,80 @@ void setup_processor(void)
|
|||||||
arc_chk_core_config();
|
arc_chk_core_config();
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int is_kernel(unsigned long addr)
|
static inline bool uboot_arg_invalid(unsigned long addr)
|
||||||
{
|
{
|
||||||
if (addr >= (unsigned long)_stext && addr <= (unsigned long)_end)
|
/*
|
||||||
return 1;
|
* Check that it is a untranslated address (although MMU is not enabled
|
||||||
return 0;
|
* yet, it being a high address ensures this is not by fluke)
|
||||||
|
*/
|
||||||
|
if (addr < PAGE_OFFSET)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
/* Check that address doesn't clobber resident kernel image */
|
||||||
|
return addr >= (unsigned long)_stext && addr <= (unsigned long)_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define IGNORE_ARGS "Ignore U-boot args: "
|
||||||
|
|
||||||
|
/* uboot_tag values for U-boot - kernel ABI revision 0; see head.S */
|
||||||
|
#define UBOOT_TAG_NONE 0
|
||||||
|
#define UBOOT_TAG_CMDLINE 1
|
||||||
|
#define UBOOT_TAG_DTB 2
|
||||||
|
|
||||||
|
void __init handle_uboot_args(void)
|
||||||
|
{
|
||||||
|
bool use_embedded_dtb = true;
|
||||||
|
bool append_cmdline = false;
|
||||||
|
|
||||||
|
#ifdef CONFIG_ARC_UBOOT_SUPPORT
|
||||||
|
/* check that we know this tag */
|
||||||
|
if (uboot_tag != UBOOT_TAG_NONE &&
|
||||||
|
uboot_tag != UBOOT_TAG_CMDLINE &&
|
||||||
|
uboot_tag != UBOOT_TAG_DTB) {
|
||||||
|
pr_warn(IGNORE_ARGS "invalid uboot tag: '%08x'\n", uboot_tag);
|
||||||
|
goto ignore_uboot_args;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uboot_tag != UBOOT_TAG_NONE &&
|
||||||
|
uboot_arg_invalid((unsigned long)uboot_arg)) {
|
||||||
|
pr_warn(IGNORE_ARGS "invalid uboot arg: '%px'\n", uboot_arg);
|
||||||
|
goto ignore_uboot_args;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* see if U-boot passed an external Device Tree blob */
|
||||||
|
if (uboot_tag == UBOOT_TAG_DTB) {
|
||||||
|
machine_desc = setup_machine_fdt((void *)uboot_arg);
|
||||||
|
|
||||||
|
/* external Device Tree blob is invalid - use embedded one */
|
||||||
|
use_embedded_dtb = !machine_desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uboot_tag == UBOOT_TAG_CMDLINE)
|
||||||
|
append_cmdline = true;
|
||||||
|
|
||||||
|
ignore_uboot_args:
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (use_embedded_dtb) {
|
||||||
|
machine_desc = setup_machine_fdt(__dtb_start);
|
||||||
|
if (!machine_desc)
|
||||||
|
panic("Embedded DT invalid\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE: @boot_command_line is populated by setup_machine_fdt() so this
|
||||||
|
* append processing can only happen after.
|
||||||
|
*/
|
||||||
|
if (append_cmdline) {
|
||||||
|
/* Ensure a whitespace between the 2 cmdlines */
|
||||||
|
strlcat(boot_command_line, " ", COMMAND_LINE_SIZE);
|
||||||
|
strlcat(boot_command_line, uboot_arg, COMMAND_LINE_SIZE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init setup_arch(char **cmdline_p)
|
void __init setup_arch(char **cmdline_p)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_ARC_UBOOT_SUPPORT
|
handle_uboot_args();
|
||||||
/* make sure that uboot passed pointer to cmdline/dtb is valid */
|
|
||||||
if (uboot_tag && is_kernel((unsigned long)uboot_arg))
|
|
||||||
panic("Invalid uboot arg\n");
|
|
||||||
|
|
||||||
/* See if u-boot passed an external Device Tree blob */
|
|
||||||
machine_desc = setup_machine_fdt(uboot_arg); /* uboot_tag == 2 */
|
|
||||||
if (!machine_desc)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
/* No, so try the embedded one */
|
|
||||||
machine_desc = setup_machine_fdt(__dtb_start);
|
|
||||||
if (!machine_desc)
|
|
||||||
panic("Embedded DT invalid\n");
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If we are here, it is established that @uboot_arg didn't
|
|
||||||
* point to DT blob. Instead if u-boot says it is cmdline,
|
|
||||||
* append to embedded DT cmdline.
|
|
||||||
* setup_machine_fdt() would have populated @boot_command_line
|
|
||||||
*/
|
|
||||||
if (uboot_tag == 1) {
|
|
||||||
/* Ensure a whitespace between the 2 cmdlines */
|
|
||||||
strlcat(boot_command_line, " ", COMMAND_LINE_SIZE);
|
|
||||||
strlcat(boot_command_line, uboot_arg,
|
|
||||||
COMMAND_LINE_SIZE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Save unparsed command line copy for /proc/cmdline */
|
/* Save unparsed command line copy for /proc/cmdline */
|
||||||
*cmdline_p = boot_command_line;
|
*cmdline_p = boot_command_line;
|
||||||
|
Loading…
Reference in New Issue
Block a user