927a351013a22cc42f51fee30d9a3d48c8445000
[oweals/u-boot.git] / arch / sparc / lib / bootm.c
1 /* SPARC code for booting linux 2.6
2  *
3  * (C) Copyright 2007
4  * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com.
5  *
6  * SPDX-License-Identifier:     GPL-2.0+
7  */
8
9 #include <common.h>
10 #include <command.h>
11 #include <asm/byteorder.h>
12 #include <asm/prom.h>
13 #include <asm/cache.h>
14 #include <image.h>
15
16 #define PRINT_KERNEL_HEADER
17
18 extern image_header_t header;
19 extern void srmmu_init_cpu(unsigned int entry);
20 extern void prepare_bootargs(char *bootargs);
21
22 /* sparc kernel argument (the ROM vector) */
23 struct linux_romvec *kernel_arg_promvec;
24
25 /* page szie is 4k */
26 #define PAGE_SIZE 0x1000
27 #define RAMDISK_IMAGE_START_MASK        0x07FF
28 #define RAMDISK_PROMPT_FLAG             0x8000
29 #define RAMDISK_LOAD_FLAG               0x4000
30 struct __attribute__ ((packed)) {
31         char traptable[PAGE_SIZE];
32         char swapper_pg_dir[PAGE_SIZE];
33         char pg0[PAGE_SIZE];
34         char pg1[PAGE_SIZE];
35         char pg2[PAGE_SIZE];
36         char pg3[PAGE_SIZE];
37         char empty_bad_page[PAGE_SIZE];
38         char empty_bad_page_table[PAGE_SIZE];
39         char empty_zero_page[PAGE_SIZE];
40         unsigned char hdr[4];   /* ascii "HdrS" */
41         /* 00.02.06.0b is for Linux kernel 2.6.11 */
42         unsigned char linuxver_mega_major;
43         unsigned char linuxver_major;
44         unsigned char linuxver_minor;
45         unsigned char linuxver_revision;
46         /* header version 0x0203 */
47         unsigned short hdr_ver;
48         union __attribute__ ((packed)) {
49                 struct __attribute__ ((packed)) {
50                         unsigned short root_flags;
51                         unsigned short root_dev;
52                         unsigned short ram_flags;
53                         unsigned int sparc_ramdisk_image;
54                         unsigned int sparc_ramdisk_size;
55                         unsigned int reboot_command;
56                         unsigned int resv[3];
57                         unsigned int end;
58                 } ver_0203;
59         } hdr_input;
60 } *linux_hdr;
61
62 /* temporary initrd image holder */
63 image_header_t ihdr;
64
65 void arch_lmb_reserve(struct lmb *lmb)
66 {
67         /* Reserve the space used by PROM and stack. This is done
68          * to avoid that the RAM image is copied over stack or
69          * PROM.
70          */
71         lmb_reserve(lmb, CONFIG_SYS_RELOC_MONITOR_BASE, CONFIG_SYS_RAM_END);
72 }
73
74 /* boot the linux kernel */
75 int do_bootm_linux(int flag, int argc, char * const argv[], bootm_headers_t * images)
76 {
77         char *bootargs;
78         ulong rd_len;
79         void (*kernel) (struct linux_romvec *, void *);
80         int ret;
81
82         /*
83          * allow the PREP bootm subcommand, it is required for bootm to work
84          */
85         if (flag & BOOTM_STATE_OS_PREP)
86                 return 0;
87
88         if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
89                 return 1;
90
91         /* Get virtual address of kernel start */
92         linux_hdr = (void *)images->os.load;
93
94         /* */
95         kernel = (void (*)(struct linux_romvec *, void *))images->ep;
96
97         /* check for a SPARC kernel */
98         if ((linux_hdr->hdr[0] != 'H') ||
99             (linux_hdr->hdr[1] != 'd') ||
100             (linux_hdr->hdr[2] != 'r') || (linux_hdr->hdr[3] != 'S')) {
101                 puts("Error reading header of SPARC Linux kernel, aborting\n");
102                 goto error;
103         }
104 #ifdef PRINT_KERNEL_HEADER
105         printf("## Found SPARC Linux kernel %d.%d.%d ...\n",
106                linux_hdr->linuxver_major,
107                linux_hdr->linuxver_minor, linux_hdr->linuxver_revision);
108 #endif
109
110         /* set basic boot params in kernel header now that it has been
111          * extracted and is writeable.
112          */
113
114         ret = image_setup_linux(images);
115         if (ret) {
116                 puts("### Failed to relocate RAM disk\n");
117                 goto error;
118         }
119
120         /* Calc length of RAM disk, if zero no ramdisk available */
121         rd_len = images->rd_end - images->rd_start;
122
123         if (rd_len) {
124                 /* Update SPARC kernel header so that Linux knows
125                  * what is going on and where to find RAM disk.
126                  *
127                  * Set INITRD Image address relative to RAM Start
128                  */
129                 linux_hdr->hdr_input.ver_0203.sparc_ramdisk_image =
130                         images->initrd_start - CONFIG_SYS_RAM_BASE;
131                 linux_hdr->hdr_input.ver_0203.sparc_ramdisk_size = rd_len;
132                 /* Clear READ ONLY flag if set to non-zero */
133                 linux_hdr->hdr_input.ver_0203.root_flags = 1;
134                 /* Set root device to: Root_RAM0 */
135                 linux_hdr->hdr_input.ver_0203.root_dev = 0x100;
136                 linux_hdr->hdr_input.ver_0203.ram_flags = 0;
137         } else {
138                 /* NOT using RAMDISK image, overwriting kernel defaults */
139                 linux_hdr->hdr_input.ver_0203.sparc_ramdisk_image = 0;
140                 linux_hdr->hdr_input.ver_0203.sparc_ramdisk_size = 0;
141                 /* Leave to kernel defaults
142                    linux_hdr->hdr_input.ver_0203.root_flags = 1;
143                    linux_hdr->hdr_input.ver_0203.root_dev = 0;
144                    linux_hdr->hdr_input.ver_0203.ram_flags = 0;
145                  */
146         }
147
148         /* Copy bootargs from bootargs variable to kernel readable area */
149         bootargs = getenv("bootargs");
150         prepare_bootargs(bootargs);
151
152         /* turn on mmu & setup context table & page table for process 0 (kernel) */
153         srmmu_init_cpu((unsigned int)kernel);
154
155         /* Enter SPARC Linux kernel
156          * From now on the only code in u-boot that will be
157          * executed is the PROM code.
158          */
159         kernel(kernel_arg_promvec, (void *)images->ep);
160
161         /* It will never come to this... */
162         while (1) ;
163
164       error:
165         return 1;
166 }