Newer
Older
/*
* Linux Kernel Parameters (passing board info data):
* r3: ptr to board info data
* r4: initrd_start or 0 if no initrd
* r5: initrd_end - unused if r4 is 0
* r6: Start of command line string
* r7: End of command line string
*/
#if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT)
if (!of_flat_tree) /* no device tree; boot old style */
(*kernel) (kbd, initrd_start, initrd_end, cmd_start, cmd_end);
/* does not return */
#if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT)
* Linux Kernel Parameters (passing device tree):
* r3: ptr to OF flat tree, followed by the board info data
* r4: physical pointer to the kernel itself
* r5: NULL
* r6: NULL
* r7: NULL
#if defined(CONFIG_OF_FLAT_TREE)
ft_setup(of_flat_tree, kbd, initrd_start, initrd_end);
/* ft_dump_blob(of_flat_tree); */
#if defined(CONFIG_OF_LIBFDT)
if (fdt_chosen(of_flat_tree, initrd_start, initrd_end, 0) < 0) {
printf("Failed creating the /chosen node (0x%08X), aborting.\n", of_flat_tree);
return;
}
#ifdef CONFIG_OF_HAS_UBOOT_ENV
if (fdt_env(of_flat_tree) < 0) {
printf("Failed creating the /u-boot-env node, aborting.\n");
return;
}
#endif
#ifdef CONFIG_OF_HAS_BD_T
if (fdt_bd_t(of_flat_tree) < 0) {
printf("Failed creating the /bd_t node, aborting.\n");
return;
}
#endif
#endif /* if defined(CONFIG_OF_LIBFDT) */
(*kernel) ((bd_t *)of_flat_tree, (ulong)kernel, 0, 0, 0);
#endif
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
static void
do_bootm_netbsd (cmd_tbl_t *cmdtp, int flag,
int argc, char *argv[],
ulong addr,
ulong *len_ptr,
int verify)
{
image_header_t *hdr = &header;
void (*loader)(bd_t *, image_header_t *, char *, char *);
image_header_t *img_addr;
char *consdev;
char *cmdline;
/*
* Booting a (NetBSD) kernel image
*
* This process is pretty similar to a standalone application:
* The (first part of an multi-) image must be a stage-2 loader,
* which in turn is responsible for loading & invoking the actual
* kernel. The only differences are the parameters being passed:
* besides the board info strucure, the loader expects a command
* line, the name of the console device, and (optionally) the
* address of the original image header.
*/
img_addr = 0;
if ((hdr->ih_type==IH_TYPE_MULTI) && (len_ptr[1]))
img_addr = (image_header_t *) addr;
consdev = "";
#if defined (CONFIG_8xx_CONS_SMC1)
consdev = "smc1";
#elif defined (CONFIG_8xx_CONS_SMC2)
consdev = "smc2";
#elif defined (CONFIG_8xx_CONS_SCC2)
consdev = "scc2";
#elif defined (CONFIG_8xx_CONS_SCC3)
consdev = "scc3";
#endif
if (argc > 2) {
ulong len;
int i;
for (i=2, len=0 ; i<argc ; i+=1)
len += strlen (argv[i]) + 1;
cmdline = malloc (len);
for (i=2, len=0 ; i<argc ; i+=1) {
if (i > 2)
cmdline[len++] = ' ';
strcpy (&cmdline[len], argv[i]);
len += strlen (argv[i]);
}
} else if ((cmdline = getenv("bootargs")) == NULL) {
cmdline = "";
}
loader = (void (*)(bd_t *, image_header_t *, char *, char *)) ntohl(hdr->ih_ep);
printf ("## Transferring control to NetBSD stage-2 loader (at address %08lx) ...\n",
(ulong)loader);
SHOW_BOOT_PROGRESS (15);
/*
* NetBSD Stage-2 Loader Parameters:
* r3: ptr to board info data
* r4: image address
* r5: console device
* r6: boot args string
*/
(*loader) (gd->bd, img_addr, consdev, cmdline);
}
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
#if defined(CONFIG_ARTOS) && defined(CONFIG_PPC)
/* Function that returns a character from the environment */
extern uchar (*env_get_char)(int);
static void
do_bootm_artos (cmd_tbl_t *cmdtp, int flag,
int argc, char *argv[],
ulong addr,
ulong *len_ptr,
int verify)
{
ulong top;
char *s, *cmdline;
char **fwenv, **ss;
int i, j, nxt, len, envno, envsz;
bd_t *kbd;
void (*entry)(bd_t *bd, char *cmdline, char **fwenv, ulong top);
image_header_t *hdr = &header;
/*
* Booting an ARTOS kernel image + application
*/
/* this used to be the top of memory, but was wrong... */
#ifdef CONFIG_PPC
/* get stack pointer */
asm volatile ("mr %0,1" : "=r"(top) );
#endif
debug ("## Current stack ends at 0x%08lX ", top);
top -= 2048; /* just to be sure */
if (top > CFG_BOOTMAPSZ)
top = CFG_BOOTMAPSZ;
top &= ~0xF;
debug ("=> set upper limit to 0x%08lX\n", top);
/* first check the artos specific boot args, then the linux args*/
if ((s = getenv("abootargs")) == NULL && (s = getenv("bootargs")) == NULL)
s = "";
/* get length of cmdline, and place it */
len = strlen(s);
top = (top - (len + 1)) & ~0xF;
cmdline = (char *)top;
debug ("## cmdline at 0x%08lX ", top);
strcpy(cmdline, s);
/* copy bdinfo */
top = (top - sizeof(bd_t)) & ~0xF;
debug ("## bd at 0x%08lX ", top);
kbd = (bd_t *)top;
memcpy(kbd, gd->bd, sizeof(bd_t));
/* first find number of env entries, and their size */
envno = 0;
envsz = 0;
for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) {
for (nxt = i; env_get_char(nxt) != '\0'; ++nxt)
;
envno++;
envsz += (nxt - i) + 1; /* plus trailing zero */
}
envno++; /* plus the terminating zero */
debug ("## %u envvars total size %u ", envno, envsz);
top = (top - sizeof(char **)*envno) & ~0xF;
fwenv = (char **)top;
debug ("## fwenv at 0x%08lX ", top);
top = (top - envsz) & ~0xF;
s = (char *)top;
ss = fwenv;
/* now copy them */
for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) {
for (nxt = i; env_get_char(nxt) != '\0'; ++nxt)
;
*ss++ = s;
for (j = i; j < nxt; ++j)
*s++ = env_get_char(j);
*s++ = '\0';
}
*ss++ = NULL; /* terminate */
entry = (void (*)(bd_t *, char *, char **, ulong))ntohl(hdr->ih_ep);
(*entry)(kbd, cmdline, fwenv, top);
}
#endif
Jon Loeliger
committed
#if (CONFIG_COMMANDS & CFG_CMD_BOOTD) || defined(CONFIG_CMD_BOOTD)
int do_bootd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
int rcode = 0;
#ifndef CFG_HUSH_PARSER
if (run_command (getenv ("bootcmd"), flag) < 0) rcode = 1;
#else
if (parse_string_outer(getenv("bootcmd"),
FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP) != 0 ) rcode = 1;
#endif
return rcode;
}
U_BOOT_CMD(
boot, 1, 1, do_bootd,
"boot - boot default, i.e., run 'bootcmd'\n",
NULL
);
/* keep old command name "bootd" for backward compatibility */
U_BOOT_CMD(
bootd, 1, 1, do_bootd,
"bootd - boot default, i.e., run 'bootcmd'\n",
NULL
);
Jon Loeliger
committed
#if (CONFIG_COMMANDS & CFG_CMD_IMI) || defined(CONFIG_CMD_IMI)
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
int do_iminfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
int arg;
ulong addr;
int rcode=0;
if (argc < 2) {
return image_info (load_addr);
}
for (arg=1; arg <argc; ++arg) {
addr = simple_strtoul(argv[arg], NULL, 16);
if (image_info (addr) != 0) rcode = 1;
}
return rcode;
}
static int image_info (ulong addr)
{
ulong data, len, checksum;
image_header_t *hdr = &header;
printf ("\n## Checking Image at %08lx ...\n", addr);
/* Copy header so we can blank CRC field for re-calculation */
memmove (&header, (char *)addr, sizeof(image_header_t));
if (ntohl(hdr->ih_magic) != IH_MAGIC) {
puts (" Bad Magic Number\n");
return 1;
}
data = (ulong)&header;
len = sizeof(image_header_t);
checksum = ntohl(hdr->ih_hcrc);
hdr->ih_hcrc = 0;
puts (" Bad Header Checksum\n");
return 1;
}
/* for multi-file images we need the data part, too */
print_image_hdr ((image_header_t *)addr);
data = addr + sizeof(image_header_t);
len = ntohl(hdr->ih_size);
puts (" Verifying Checksum ... ");
if (crc32 (0, (uchar *)data, len) != ntohl(hdr->ih_dcrc)) {
U_BOOT_CMD(
iminfo, CFG_MAXARGS, 1, do_iminfo,
"iminfo - print header information for application image\n",
"addr [addr ...]\n"
" - print header information for application image starting at\n"
" address 'addr' in memory; this includes verification of the\n"
" image contents (magic number, header and payload checksums)\n"
);
Jon Loeliger
committed
#if (CONFIG_COMMANDS & CFG_CMD_IMLS) || defined(CONFIG_CMD_IMLS)
/*-----------------------------------------------------------------------
* List all images found in flash.
*/
int do_imls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
flash_info_t *info;
int i, j;
image_header_t *hdr;
ulong data, len, checksum;
for (i=0, info=&flash_info[0]; i<CFG_MAX_FLASH_BANKS; ++i, ++info) {
if (info->flash_id == FLASH_UNKNOWN)
goto next_bank;
for (j=0; j<info->sector_count; ++j) {
if (!(hdr=(image_header_t *)info->start[j]) ||
(ntohl(hdr->ih_magic) != IH_MAGIC))
goto next_sector;
/* Copy header so we can blank CRC field for re-calculation */
memmove (&header, (char *)hdr, sizeof(image_header_t));
checksum = ntohl(header.ih_hcrc);
header.ih_hcrc = 0;
if (crc32 (0, (uchar *)&header, sizeof(image_header_t))
!= checksum)
goto next_sector;
printf ("Image at %08lX:\n", (ulong)hdr);
print_image_hdr( hdr );
data = (ulong)hdr + sizeof(image_header_t);
len = ntohl(hdr->ih_size);
puts (" Verifying Checksum ... ");
if (crc32 (0, (uchar *)data, len) != ntohl(hdr->ih_dcrc)) {
}
return (0);
}
U_BOOT_CMD(
imls, 1, 1, do_imls,
"imls - list all images found in flash\n",
"\n"
" - Prints information about all images found at sector\n"
" boundaries in flash.\n"
);
#endif /* CFG_CMD_IMLS */
void
print_image_hdr (image_header_t *hdr)
{
Jon Loeliger
committed
#if (CONFIG_COMMANDS & CFG_CMD_DATE) || defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE)
time_t timestamp = (time_t)ntohl(hdr->ih_time);
struct rtc_time tm;
#endif
printf (" Image Name: %.*s\n", IH_NMLEN, hdr->ih_name);
Jon Loeliger
committed
#if (CONFIG_COMMANDS & CFG_CMD_DATE) || defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE)
to_tm (timestamp, &tm);
printf (" Created: %4d-%02d-%02d %2d:%02d:%02d UTC\n",
tm.tm_year, tm.tm_mon, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec);
#endif /* CFG_CMD_DATE, CONFIG_TIMESTAMP */
puts (" Image Type: "); print_type(hdr);
printf ("\n Data Size: %d Bytes = ", ntohl(hdr->ih_size));
printf (" Load Address: %08x\n"
" Entry Point: %08x\n",
ntohl(hdr->ih_load), ntohl(hdr->ih_ep));
if (hdr->ih_type == IH_TYPE_MULTI) {
int i;
ulong len;
ulong *len_ptr = (ulong *)((ulong)hdr + sizeof(image_header_t));
for (i=0; (len = ntohl(*len_ptr)); ++i, ++len_ptr) {
printf (" Image %d: %8ld Bytes = ", i, len);
print_size (len, "\n");
}
}
}
static void
print_type (image_header_t *hdr)
{
char *os, *arch, *type, *comp;
switch (hdr->ih_os) {
case IH_OS_INVALID: os = "Invalid OS"; break;
case IH_OS_NETBSD: os = "NetBSD"; break;
case IH_OS_LINUX: os = "Linux"; break;
case IH_OS_VXWORKS: os = "VxWorks"; break;
case IH_OS_QNX: os = "QNX"; break;
case IH_OS_U_BOOT: os = "U-Boot"; break;
case IH_OS_RTEMS: os = "RTEMS"; break;
#ifdef CONFIG_ARTOS
case IH_OS_ARTOS: os = "ARTOS"; break;
#endif
#ifdef CONFIG_LYNXKDI
case IH_OS_LYNXOS: os = "LynxOS"; break;
default: os = "Unknown OS"; break;
}
switch (hdr->ih_arch) {
case IH_CPU_INVALID: arch = "Invalid CPU"; break;
case IH_CPU_ALPHA: arch = "Alpha"; break;
case IH_CPU_ARM: arch = "ARM"; break;
case IH_CPU_BLACKFIN: arch = "Blackfin"; break;
case IH_CPU_I386: arch = "Intel x86"; break;
case IH_CPU_IA64: arch = "IA64"; break;
case IH_CPU_M68K: arch = "M68K"; break;
case IH_CPU_MICROBLAZE: arch = "Microblaze"; break;
case IH_CPU_MIPS: arch = "MIPS"; break;
case IH_CPU_NIOS2: arch = "Nios-II"; break;
case IH_CPU_NIOS: arch = "Nios"; break;
case IH_CPU_PPC: arch = "PowerPC"; break;
case IH_CPU_S390: arch = "IBM S390"; break;
case IH_CPU_SH: arch = "SuperH"; break;
case IH_CPU_SPARC64: arch = "SPARC 64 Bit"; break;
case IH_CPU_SPARC: arch = "SPARC"; break;
default: arch = "Unknown Architecture"; break;
}
switch (hdr->ih_type) {
case IH_TYPE_INVALID: type = "Invalid Image"; break;
case IH_TYPE_STANDALONE:type = "Standalone Program"; break;
case IH_TYPE_KERNEL: type = "Kernel Image"; break;
case IH_TYPE_RAMDISK: type = "RAMDisk Image"; break;
case IH_TYPE_MULTI: type = "Multi-File Image"; break;
case IH_TYPE_FIRMWARE: type = "Firmware"; break;
case IH_TYPE_SCRIPT: type = "Script"; break;
case IH_TYPE_FLATDT: type = "Flat Device Tree"; break;
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
default: type = "Unknown Image"; break;
}
switch (hdr->ih_comp) {
case IH_COMP_NONE: comp = "uncompressed"; break;
case IH_COMP_GZIP: comp = "gzip compressed"; break;
case IH_COMP_BZIP2: comp = "bzip2 compressed"; break;
default: comp = "unknown compression"; break;
}
printf ("%s %s %s (%s)", arch, os, type, comp);
}
#define ZALLOC_ALIGNMENT 16
static void *zalloc(void *x, unsigned items, unsigned size)
{
void *p;
size *= items;
size = (size + ZALLOC_ALIGNMENT - 1) & ~(ZALLOC_ALIGNMENT - 1);
p = malloc (size);
return (p);
}
static void zfree(void *x, void *addr, unsigned nb)
{
free (addr);
}
#define HEAD_CRC 2
#define EXTRA_FIELD 4
#define ORIG_NAME 8
#define COMMENT 0x10
#define RESERVED 0xe0
#define DEFLATED 8
int gunzip(void *dst, int dstlen, unsigned char *src, unsigned long *lenp)
{
z_stream s;
int r, i, flags;
/* skip header */
i = 10;
flags = src[3];
if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
puts ("Error: Bad gzipped data\n");
return (-1);
}
if ((flags & EXTRA_FIELD) != 0)
i = 12 + src[10] + (src[11] << 8);
if ((flags & ORIG_NAME) != 0)
while (src[i++] != 0)
;
if ((flags & COMMENT) != 0)
while (src[i++] != 0)
;
if ((flags & HEAD_CRC) != 0)
i += 2;
if (i >= *lenp) {
puts ("Error: gunzip out of data in header\n");
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
return (-1);
}
s.zalloc = zalloc;
s.zfree = zfree;
#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
s.outcb = (cb_func)WATCHDOG_RESET;
#else
s.outcb = Z_NULL;
#endif /* CONFIG_HW_WATCHDOG */
r = inflateInit2(&s, -MAX_WBITS);
if (r != Z_OK) {
printf ("Error: inflateInit2() returned %d\n", r);
return (-1);
}
s.next_in = src + i;
s.avail_in = *lenp - i;
s.next_out = dst;
s.avail_out = dstlen;
r = inflate(&s, Z_FINISH);
if (r != Z_OK && r != Z_STREAM_END) {
printf ("Error: inflate() returned %d\n", r);
return (-1);
}
*lenp = s.next_out - (unsigned char *) dst;
inflateEnd(&s);
return (0);
}
#ifdef CONFIG_BZIP2
void bz_internal_error(int errcode)
{
printf ("BZIP2 internal error %d\n", errcode);
}
#endif /* CONFIG_BZIP2 */
static void
do_bootm_rtems (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
ulong addr, ulong *len_ptr, int verify)
{
image_header_t *hdr = &header;
void (*entry_point)(bd_t *);
entry_point = (void (*)(bd_t *)) ntohl(hdr->ih_ep);
printf ("## Transferring control to RTEMS (at address %08lx) ...\n",
(ulong)entry_point);
SHOW_BOOT_PROGRESS (15);
/*
* RTEMS Parameters:
* r3: ptr to board info data
*/
(*entry_point ) ( gd->bd );
}
Jon Loeliger
committed
#if (CONFIG_COMMANDS & CFG_CMD_ELF) || defined(CONFIG_CMD_ELF)
static void
do_bootm_vxworks (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
ulong addr, ulong *len_ptr, int verify)
{
image_header_t *hdr = &header;
char str[80];
sprintf(str, "%x", ntohl(hdr->ih_ep)); /* write entry-point into string */
setenv("loadaddr", str);
do_bootvx(cmdtp, 0, 0, NULL);
}
static void
do_bootm_qnxelf (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
ulong addr, ulong *len_ptr, int verify)
{
image_header_t *hdr = &header;
char *local_args[2];
char str[16];
sprintf(str, "%x", ntohl(hdr->ih_ep)); /* write entry-point into string */
local_args[0] = argv[0];
local_args[1] = str; /* and provide it via the arguments */
do_bootelf(cmdtp, 0, 2, local_args);
}
#endif /* CFG_CMD_ELF */
#ifdef CONFIG_LYNXKDI
static void
do_bootm_lynxkdi (cmd_tbl_t *cmdtp, int flag,
int argc, char *argv[],
ulong addr,
ulong *len_ptr,
int verify)
{
lynxkdi_boot( &header );
}
#endif /* CONFIG_LYNXKDI */