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