1ea0364f1SPeter Tyser /* 2ea0364f1SPeter Tyser * (C) Copyright 2002 3ea0364f1SPeter Tyser * Sysgo Real-Time Solutions, GmbH <www.elinos.com> 4ea0364f1SPeter Tyser * Marius Groeger <mgroeger@sysgo.de> 5ea0364f1SPeter Tyser * 6ea0364f1SPeter Tyser * Copyright (C) 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) 7ea0364f1SPeter Tyser * 8ea0364f1SPeter Tyser * This program is free software; you can redistribute it and/or modify 9ea0364f1SPeter Tyser * it under the terms of the GNU General Public License as published by 10ea0364f1SPeter Tyser * the Free Software Foundation; either version 2 of the License, or 11ea0364f1SPeter Tyser * (at your option) any later version. 12ea0364f1SPeter Tyser * 13ea0364f1SPeter Tyser * This program is distributed in the hope that it will be useful, 14ea0364f1SPeter Tyser * but WITHOUT ANY WARRANTY; without even the implied warranty of 15ea0364f1SPeter Tyser * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16ea0364f1SPeter Tyser * GNU General Public License for more details. 17ea0364f1SPeter Tyser * 18ea0364f1SPeter Tyser * You should have received a copy of the GNU General Public License 19ea0364f1SPeter Tyser * along with this program; if not, write to the Free Software 20ea0364f1SPeter Tyser * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21ea0364f1SPeter Tyser * 22ea0364f1SPeter Tyser */ 23ea0364f1SPeter Tyser 24ea0364f1SPeter Tyser #include <common.h> 25ea0364f1SPeter Tyser #include <command.h> 26ea0364f1SPeter Tyser #include <image.h> 27ea0364f1SPeter Tyser #include <u-boot/zlib.h> 28ea0364f1SPeter Tyser #include <asm/byteorder.h> 29ea0364f1SPeter Tyser 30ea0364f1SPeter Tyser DECLARE_GLOBAL_DATA_PTR; 31ea0364f1SPeter Tyser 32ea0364f1SPeter Tyser #if defined (CONFIG_SETUP_MEMORY_TAGS) || \ 33ea0364f1SPeter Tyser defined (CONFIG_CMDLINE_TAG) || \ 34ea0364f1SPeter Tyser defined (CONFIG_INITRD_TAG) || \ 35ea0364f1SPeter Tyser defined (CONFIG_SERIAL_TAG) || \ 36*47ea6edfSMinkyu Kang defined (CONFIG_REVISION_TAG) 37ea0364f1SPeter Tyser static void setup_start_tag (bd_t *bd); 38ea0364f1SPeter Tyser 39ea0364f1SPeter Tyser # ifdef CONFIG_SETUP_MEMORY_TAGS 40ea0364f1SPeter Tyser static void setup_memory_tags (bd_t *bd); 41ea0364f1SPeter Tyser # endif 42ea0364f1SPeter Tyser static void setup_commandline_tag (bd_t *bd, char *commandline); 43ea0364f1SPeter Tyser 44ea0364f1SPeter Tyser # ifdef CONFIG_INITRD_TAG 45ea0364f1SPeter Tyser static void setup_initrd_tag (bd_t *bd, ulong initrd_start, 46ea0364f1SPeter Tyser ulong initrd_end); 47ea0364f1SPeter Tyser # endif 48ea0364f1SPeter Tyser static void setup_end_tag (bd_t *bd); 49ea0364f1SPeter Tyser 50ea0364f1SPeter Tyser static struct tag *params; 51ea0364f1SPeter Tyser #endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */ 52ea0364f1SPeter Tyser 53ea0364f1SPeter Tyser int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) 54ea0364f1SPeter Tyser { 55ea0364f1SPeter Tyser bd_t *bd = gd->bd; 56ea0364f1SPeter Tyser char *s; 57ea0364f1SPeter Tyser int machid = bd->bi_arch_number; 58ea0364f1SPeter Tyser void (*theKernel)(int zero, int arch, uint params); 59ea0364f1SPeter Tyser 60ea0364f1SPeter Tyser #ifdef CONFIG_CMDLINE_TAG 61ea0364f1SPeter Tyser char *commandline = getenv ("bootargs"); 62ea0364f1SPeter Tyser #endif 63ea0364f1SPeter Tyser 64ea0364f1SPeter Tyser if ((flag != 0) && (flag != BOOTM_STATE_OS_GO)) 65ea0364f1SPeter Tyser return 1; 66ea0364f1SPeter Tyser 67ea0364f1SPeter Tyser theKernel = (void (*)(int, int, uint))images->ep; 68ea0364f1SPeter Tyser 69ea0364f1SPeter Tyser s = getenv ("machid"); 70ea0364f1SPeter Tyser if (s) { 71ea0364f1SPeter Tyser machid = simple_strtoul (s, NULL, 16); 72ea0364f1SPeter Tyser printf ("Using machid 0x%x from environment\n", machid); 73ea0364f1SPeter Tyser } 74ea0364f1SPeter Tyser 75ea0364f1SPeter Tyser show_boot_progress (15); 76ea0364f1SPeter Tyser 77ea0364f1SPeter Tyser debug ("## Transferring control to Linux (at address %08lx) ...\n", 78ea0364f1SPeter Tyser (ulong) theKernel); 79ea0364f1SPeter Tyser 80ea0364f1SPeter Tyser #if defined (CONFIG_SETUP_MEMORY_TAGS) || \ 81ea0364f1SPeter Tyser defined (CONFIG_CMDLINE_TAG) || \ 82ea0364f1SPeter Tyser defined (CONFIG_INITRD_TAG) || \ 83ea0364f1SPeter Tyser defined (CONFIG_SERIAL_TAG) || \ 84*47ea6edfSMinkyu Kang defined (CONFIG_REVISION_TAG) 85ea0364f1SPeter Tyser setup_start_tag (bd); 86ea0364f1SPeter Tyser #ifdef CONFIG_SERIAL_TAG 87ea0364f1SPeter Tyser setup_serial_tag (¶ms); 88ea0364f1SPeter Tyser #endif 89ea0364f1SPeter Tyser #ifdef CONFIG_REVISION_TAG 90ea0364f1SPeter Tyser setup_revision_tag (¶ms); 91ea0364f1SPeter Tyser #endif 92ea0364f1SPeter Tyser #ifdef CONFIG_SETUP_MEMORY_TAGS 93ea0364f1SPeter Tyser setup_memory_tags (bd); 94ea0364f1SPeter Tyser #endif 95ea0364f1SPeter Tyser #ifdef CONFIG_CMDLINE_TAG 96ea0364f1SPeter Tyser setup_commandline_tag (bd, commandline); 97ea0364f1SPeter Tyser #endif 98ea0364f1SPeter Tyser #ifdef CONFIG_INITRD_TAG 99ea0364f1SPeter Tyser if (images->rd_start && images->rd_end) 100ea0364f1SPeter Tyser setup_initrd_tag (bd, images->rd_start, images->rd_end); 101ea0364f1SPeter Tyser #endif 102ea0364f1SPeter Tyser setup_end_tag (bd); 103ea0364f1SPeter Tyser #endif 104ea0364f1SPeter Tyser 105ea0364f1SPeter Tyser /* we assume that the kernel is in place */ 106ea0364f1SPeter Tyser printf ("\nStarting kernel ...\n\n"); 107ea0364f1SPeter Tyser 108ea0364f1SPeter Tyser #ifdef CONFIG_USB_DEVICE 109ea0364f1SPeter Tyser { 110ea0364f1SPeter Tyser extern void udc_disconnect (void); 111ea0364f1SPeter Tyser udc_disconnect (); 112ea0364f1SPeter Tyser } 113ea0364f1SPeter Tyser #endif 114ea0364f1SPeter Tyser 115ea0364f1SPeter Tyser cleanup_before_linux (); 116ea0364f1SPeter Tyser 117ea0364f1SPeter Tyser theKernel (0, machid, bd->bi_boot_params); 118ea0364f1SPeter Tyser /* does not return */ 119ea0364f1SPeter Tyser 120ea0364f1SPeter Tyser return 1; 121ea0364f1SPeter Tyser } 122ea0364f1SPeter Tyser 123ea0364f1SPeter Tyser 124ea0364f1SPeter Tyser #if defined (CONFIG_SETUP_MEMORY_TAGS) || \ 125ea0364f1SPeter Tyser defined (CONFIG_CMDLINE_TAG) || \ 126ea0364f1SPeter Tyser defined (CONFIG_INITRD_TAG) || \ 127ea0364f1SPeter Tyser defined (CONFIG_SERIAL_TAG) || \ 128*47ea6edfSMinkyu Kang defined (CONFIG_REVISION_TAG) 129ea0364f1SPeter Tyser static void setup_start_tag (bd_t *bd) 130ea0364f1SPeter Tyser { 131ea0364f1SPeter Tyser params = (struct tag *) bd->bi_boot_params; 132ea0364f1SPeter Tyser 133ea0364f1SPeter Tyser params->hdr.tag = ATAG_CORE; 134ea0364f1SPeter Tyser params->hdr.size = tag_size (tag_core); 135ea0364f1SPeter Tyser 136ea0364f1SPeter Tyser params->u.core.flags = 0; 137ea0364f1SPeter Tyser params->u.core.pagesize = 0; 138ea0364f1SPeter Tyser params->u.core.rootdev = 0; 139ea0364f1SPeter Tyser 140ea0364f1SPeter Tyser params = tag_next (params); 141ea0364f1SPeter Tyser } 142ea0364f1SPeter Tyser 143ea0364f1SPeter Tyser 144ea0364f1SPeter Tyser #ifdef CONFIG_SETUP_MEMORY_TAGS 145ea0364f1SPeter Tyser static void setup_memory_tags (bd_t *bd) 146ea0364f1SPeter Tyser { 147ea0364f1SPeter Tyser int i; 148ea0364f1SPeter Tyser 149ea0364f1SPeter Tyser for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { 150ea0364f1SPeter Tyser params->hdr.tag = ATAG_MEM; 151ea0364f1SPeter Tyser params->hdr.size = tag_size (tag_mem32); 152ea0364f1SPeter Tyser 153ea0364f1SPeter Tyser params->u.mem.start = bd->bi_dram[i].start; 154ea0364f1SPeter Tyser params->u.mem.size = bd->bi_dram[i].size; 155ea0364f1SPeter Tyser 156ea0364f1SPeter Tyser params = tag_next (params); 157ea0364f1SPeter Tyser } 158ea0364f1SPeter Tyser } 159ea0364f1SPeter Tyser #endif /* CONFIG_SETUP_MEMORY_TAGS */ 160ea0364f1SPeter Tyser 161ea0364f1SPeter Tyser 162ea0364f1SPeter Tyser static void setup_commandline_tag (bd_t *bd, char *commandline) 163ea0364f1SPeter Tyser { 164ea0364f1SPeter Tyser char *p; 165ea0364f1SPeter Tyser 166ea0364f1SPeter Tyser if (!commandline) 167ea0364f1SPeter Tyser return; 168ea0364f1SPeter Tyser 169ea0364f1SPeter Tyser /* eat leading white space */ 170ea0364f1SPeter Tyser for (p = commandline; *p == ' '; p++); 171ea0364f1SPeter Tyser 172ea0364f1SPeter Tyser /* skip non-existent command lines so the kernel will still 173ea0364f1SPeter Tyser * use its default command line. 174ea0364f1SPeter Tyser */ 175ea0364f1SPeter Tyser if (*p == '\0') 176ea0364f1SPeter Tyser return; 177ea0364f1SPeter Tyser 178ea0364f1SPeter Tyser params->hdr.tag = ATAG_CMDLINE; 179ea0364f1SPeter Tyser params->hdr.size = 180ea0364f1SPeter Tyser (sizeof (struct tag_header) + strlen (p) + 1 + 4) >> 2; 181ea0364f1SPeter Tyser 182ea0364f1SPeter Tyser strcpy (params->u.cmdline.cmdline, p); 183ea0364f1SPeter Tyser 184ea0364f1SPeter Tyser params = tag_next (params); 185ea0364f1SPeter Tyser } 186ea0364f1SPeter Tyser 187ea0364f1SPeter Tyser 188ea0364f1SPeter Tyser #ifdef CONFIG_INITRD_TAG 189ea0364f1SPeter Tyser static void setup_initrd_tag (bd_t *bd, ulong initrd_start, ulong initrd_end) 190ea0364f1SPeter Tyser { 191ea0364f1SPeter Tyser /* an ATAG_INITRD node tells the kernel where the compressed 192ea0364f1SPeter Tyser * ramdisk can be found. ATAG_RDIMG is a better name, actually. 193ea0364f1SPeter Tyser */ 194ea0364f1SPeter Tyser params->hdr.tag = ATAG_INITRD2; 195ea0364f1SPeter Tyser params->hdr.size = tag_size (tag_initrd); 196ea0364f1SPeter Tyser 197ea0364f1SPeter Tyser params->u.initrd.start = initrd_start; 198ea0364f1SPeter Tyser params->u.initrd.size = initrd_end - initrd_start; 199ea0364f1SPeter Tyser 200ea0364f1SPeter Tyser params = tag_next (params); 201ea0364f1SPeter Tyser } 202ea0364f1SPeter Tyser #endif /* CONFIG_INITRD_TAG */ 203ea0364f1SPeter Tyser 204ea0364f1SPeter Tyser #ifdef CONFIG_SERIAL_TAG 205ea0364f1SPeter Tyser void setup_serial_tag (struct tag **tmp) 206ea0364f1SPeter Tyser { 207ea0364f1SPeter Tyser struct tag *params = *tmp; 208ea0364f1SPeter Tyser struct tag_serialnr serialnr; 209ea0364f1SPeter Tyser void get_board_serial(struct tag_serialnr *serialnr); 210ea0364f1SPeter Tyser 211ea0364f1SPeter Tyser get_board_serial(&serialnr); 212ea0364f1SPeter Tyser params->hdr.tag = ATAG_SERIAL; 213ea0364f1SPeter Tyser params->hdr.size = tag_size (tag_serialnr); 214ea0364f1SPeter Tyser params->u.serialnr.low = serialnr.low; 215ea0364f1SPeter Tyser params->u.serialnr.high= serialnr.high; 216ea0364f1SPeter Tyser params = tag_next (params); 217ea0364f1SPeter Tyser *tmp = params; 218ea0364f1SPeter Tyser } 219ea0364f1SPeter Tyser #endif 220ea0364f1SPeter Tyser 221ea0364f1SPeter Tyser #ifdef CONFIG_REVISION_TAG 222ea0364f1SPeter Tyser void setup_revision_tag(struct tag **in_params) 223ea0364f1SPeter Tyser { 224ea0364f1SPeter Tyser u32 rev = 0; 225ea0364f1SPeter Tyser u32 get_board_rev(void); 226ea0364f1SPeter Tyser 227ea0364f1SPeter Tyser rev = get_board_rev(); 228ea0364f1SPeter Tyser params->hdr.tag = ATAG_REVISION; 229ea0364f1SPeter Tyser params->hdr.size = tag_size (tag_revision); 230ea0364f1SPeter Tyser params->u.revision.rev = rev; 231ea0364f1SPeter Tyser params = tag_next (params); 232ea0364f1SPeter Tyser } 233ea0364f1SPeter Tyser #endif /* CONFIG_REVISION_TAG */ 234ea0364f1SPeter Tyser 235ea0364f1SPeter Tyser 236ea0364f1SPeter Tyser static void setup_end_tag (bd_t *bd) 237ea0364f1SPeter Tyser { 238ea0364f1SPeter Tyser params->hdr.tag = ATAG_NONE; 239ea0364f1SPeter Tyser params->hdr.size = 0; 240ea0364f1SPeter Tyser } 241ea0364f1SPeter Tyser 242ea0364f1SPeter Tyser #endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */ 243