blob: 8a0010be23797d4ac075e0b5818d7d7e11e3e284 [file] [log] [blame]
Nobuhiro Iwamatsu0b135cf2007-05-13 20:58:00 +09001/*
2 * (C) Copyright 2003
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
Nobuhiro Iwamatsu6b44a432008-09-17 11:08:36 +09005 * (c) Copyright 2008 Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com>
6 * (c) Copyright 2008 Renesas Solutions Corp.
7 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02008 * SPDX-License-Identifier: GPL-2.0+
Nobuhiro Iwamatsu0b135cf2007-05-13 20:58:00 +09009 */
10
11#include <common.h>
12#include <command.h>
13#include <asm/byteorder.h>
Nobuhiro Iwamatsu9980df52010-12-08 13:46:36 +090014#include <asm/zimage.h>
Nobuhiro Iwamatsu0b135cf2007-05-13 20:58:00 +090015
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020016#ifdef CONFIG_SYS_DEBUG
Nobuhiro Iwamatsu6b44a432008-09-17 11:08:36 +090017static void hexdump(unsigned char *buf, int len)
Nobuhiro Iwamatsu0b135cf2007-05-13 20:58:00 +090018{
19 int i;
20
21 for (i = 0; i < len; i++) {
22 if ((i % 16) == 0)
Nobuhiro Iwamatsu6b44a432008-09-17 11:08:36 +090023 printf("%s%08x: ", i ? "\n" : "",
24 (unsigned int)&buf[i]);
25 printf("%02x ", buf[i]);
Nobuhiro Iwamatsu0b135cf2007-05-13 20:58:00 +090026 }
Nobuhiro Iwamatsu6b44a432008-09-17 11:08:36 +090027 printf("\n");
Nobuhiro Iwamatsu0b135cf2007-05-13 20:58:00 +090028}
29#endif
30
Nobuhiro Iwamatsucf2c87d2010-09-28 12:14:57 +090031#ifdef CONFIG_SH_SDRAM_OFFSET
32#define GET_INITRD_START(initrd, linux) (initrd - linux + CONFIG_SH_SDRAM_OFFSET)
33#else
34#define GET_INITRD_START(initrd, linux) (initrd - linux)
35#endif
36
37static void set_sh_linux_param(unsigned long param_addr, unsigned long data)
38{
39 *(unsigned long *)(param_addr) = data;
40}
41
42static unsigned long sh_check_cmd_arg(char *cmdline, char *key, int base)
43{
44 unsigned long val = 0;
45 char *p = strstr(cmdline, key);
46 if (p) {
47 p += strlen(key);
48 val = simple_strtol(p, NULL, base);
49 }
50 return val;
51}
52
Wolfgang Denk54841ab2010-06-28 22:00:46 +020053int do_bootm_linux(int flag, int argc, char * const argv[], bootm_headers_t *images)
Nobuhiro Iwamatsu0b135cf2007-05-13 20:58:00 +090054{
Nobuhiro Iwamatsu6b44a432008-09-17 11:08:36 +090055 /* Linux kernel load address */
Kumar Galac160a952008-08-15 08:24:36 -050056 void (*kernel) (void) = (void (*)(void))images->ep;
Nobuhiro Iwamatsu6b44a432008-09-17 11:08:36 +090057 /* empty_zero_page */
Nobuhiro Iwamatsub5d10a12008-09-18 19:34:36 +090058 unsigned char *param
59 = (unsigned char *)image_get_load(images->legacy_hdr_os);
Nobuhiro Iwamatsu6b44a432008-09-17 11:08:36 +090060 /* Linux kernel command line */
Nobuhiro Iwamatsucf2c87d2010-09-28 12:14:57 +090061 char *cmdline = (char *)param + COMMAND_LINE;
Nobuhiro Iwamatsu6b44a432008-09-17 11:08:36 +090062 /* PAGE_SIZE */
Nobuhiro Iwamatsub5d10a12008-09-18 19:34:36 +090063 unsigned long size = images->ep - (unsigned long)param;
Nobuhiro Iwamatsu6b44a432008-09-17 11:08:36 +090064 char *bootargs = getenv("bootargs");
Nobuhiro Iwamatsu0b135cf2007-05-13 20:58:00 +090065
Andreas Bießmann2cb0e552013-07-02 13:57:44 +020066 /*
67 * allow the PREP bootm subcommand, it is required for bootm to work
68 */
69 if (flag & BOOTM_STATE_OS_PREP)
70 return 0;
71
Kumar Gala49c3a862008-10-21 17:25:45 -050072 if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
73 return 1;
74
Nobuhiro Iwamatsu9980df52010-12-08 13:46:36 +090075 /* Clear zero page */
76 memset(param, 0, size);
Nobuhiro Iwamatsucf2c87d2010-09-28 12:14:57 +090077
78 /* Set commandline */
Nobuhiro Iwamatsu6b44a432008-09-17 11:08:36 +090079 strcpy(cmdline, bootargs);
Nobuhiro Iwamatsub02bad12007-09-23 02:12:30 +090080
Nobuhiro Iwamatsucf2c87d2010-09-28 12:14:57 +090081 /* Initrd */
82 if (images->rd_start || images->rd_end) {
Nobuhiro Iwamatsude03f8b2010-10-19 17:14:15 +090083 unsigned long ramdisk_flags = 0;
Nobuhiro Iwamatsucf2c87d2010-09-28 12:14:57 +090084 int val = sh_check_cmd_arg(bootargs, CMD_ARG_RD_PROMPT, 10);
85 if (val == 1)
86 ramdisk_flags |= RD_PROMPT;
87 else
88 ramdisk_flags &= ~RD_PROMPT;
Wolfgang Denk071bc922010-10-27 22:48:30 +020089
Nobuhiro Iwamatsucf2c87d2010-09-28 12:14:57 +090090 val = sh_check_cmd_arg(bootargs, CMD_ARG_RD_DOLOAD, 10);
91 if (val == 1)
92 ramdisk_flags |= RD_DOLOAD;
93 else
94 ramdisk_flags &= ~RD_DOLOAD;
95
96 set_sh_linux_param((unsigned long)param + MOUNT_ROOT_RDONLY, 0x0001);
97 set_sh_linux_param((unsigned long)param + RAMDISK_FLAGS, ramdisk_flags);
98 set_sh_linux_param((unsigned long)param + ORIG_ROOT_DEV, 0x0200);
99 set_sh_linux_param((unsigned long)param + LOADER_TYPE, 0x0001);
100 set_sh_linux_param((unsigned long)param + INITRD_START,
101 GET_INITRD_START(images->rd_start, CONFIG_SYS_SDRAM_BASE));
102 set_sh_linux_param((unsigned long)param + INITRD_SIZE,
103 images->rd_end - images->rd_start);
104 }
105
106 /* Boot kernel */
Nobuhiro Iwamatsu0b135cf2007-05-13 20:58:00 +0900107 kernel();
Marian Balakowiczcd7c5962008-03-12 10:33:00 +0100108
Nobuhiro Iwamatsu9980df52010-12-08 13:46:36 +0900109 /* does not return */
Kumar Gala40d7e992008-08-15 08:24:45 -0500110 return 1;
Nobuhiro Iwamatsu0b135cf2007-05-13 20:58:00 +0900111}