blob: 7c3dc49df5a75a7057ab058194c01582057bd36b [file] [log] [blame]
Alek Dub379eef2008-05-21 13:37:04 +08001/*
Sylvain Chouleur88c2e832015-02-27 13:59:16 +01002 * bootstub 32 bit entry setting routings
Alek Duf21b9a32010-05-27 14:23:43 +08003 *
4 * Copyright (C) 2008-2010 Intel Corporation.
5 * Author: Alek Du <alek.du@intel.com>
Alek Dub379eef2008-05-21 13:37:04 +08006 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU General Public License,
9 * version 2, as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
Sylvain Chouleur88c2e832015-02-27 13:59:16 +010017 * this program; if not, write to the Free Software Foundation, Inc.,
Alek Dub379eef2008-05-21 13:37:04 +080018 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
19 *
Alek Dub7f7baf2008-05-13 16:23:15 +080020 */
21
22#include "types.h"
23#include "bootstub.h"
24#include "bootparam.h"
Alek Duc8496d12008-07-10 14:46:17 +080025#include "spi-uart.h"
Mark F. Brown90847a82011-09-07 18:06:24 -040026#include "ssp-uart.h"
Evgeny Kalugin8e8bf002013-10-24 11:21:07 +030027#include "mb.h"
Feng Tang7cc52cd2009-06-01 11:23:28 +080028#include "sfi.h"
Sylvain Chouleur88c2e832015-02-27 13:59:16 +010029#include <bootimg.h>
Alek Duc8496d12008-07-10 14:46:17 +080030
Evgeny Kalugin8e8bf002013-10-24 11:21:07 +030031#include <stdint.h>
32#include <stddef.h>
33#include "imr_toc.h"
34
35#define PAGE_SIZE_MASK 0xFFF
36#define MASK_1K 0x3FF
37#define PAGE_ALIGN_FWD(x) ((x + PAGE_SIZE_MASK) & ~PAGE_SIZE_MASK)
38#define PAGE_ALIGN_BACK(x) ((x) & ~PAGE_SIZE_MASK)
39
40#define IMR_START_ADDRESS(x) (((x) & 0xFFFFFFFC) << 8)
41#define IMR_END_ADDRESS(x) ((x == 0) ? (x) : ((((x) & 0xFFFFFFFC) << 8) | MASK_1K))
42
43#define IMR6_START_ADDRESS IMR_START_ADDRESS(*((u32 *)0xff108160))
44#define IMR6_END_ADDRESS IMR_END_ADDRESS(*((u32 *)0xff108164))
45#define IMR7_START_ADDRESS IMR_START_ADDRESS(*((u32 *)0xff108170))
46#define IMR7_END_ADDRESS IMR_END_ADDRESS(*((u32 *)0xff108174))
47
48#define FATAL_HANG() { asm("cli"); while (1) { asm("nop"); } }
49
Eric Ernstaecaba32013-04-02 12:02:59 -070050extern int no_uart_used;
51
Evgeny Kalugin8e8bf002013-10-24 11:21:07 +030052extern imr_toc_t imr6_toc;
53static u32 imr7_size;
54
55static u32 sps_load_adrs;
56
57static memory_map_t mb_mmap[E820MAX];
58u32 mb_magic, mb_info;
59
60struct gdt_ptr {
61 u16 len;
62 u32 ptr;
63} __attribute__((packed));
64
Alek Dub7f7baf2008-05-13 16:23:15 +080065static void *memcpy(void *dest, const void *src, size_t count)
66{
67 char *tmp = dest;
68 const char *s = src;
Alek Dua24ea5c2009-05-26 09:56:47 +080069 size_t _count = count / 4;
Alek Dub7f7baf2008-05-13 16:23:15 +080070
Alek Dua24ea5c2009-05-26 09:56:47 +080071 while (_count--) {
72 *(long *)tmp = *(long *)s;
73 tmp += 4;
74 s += 4;
75 }
76 count %= 4;
Alek Dub7f7baf2008-05-13 16:23:15 +080077 while (count--)
78 *tmp++ = *s++;
79 return dest;
80}
81
Alek Dua24ea5c2009-05-26 09:56:47 +080082static void *memset(void *s, unsigned char c, size_t count)
Alek Dub7f7baf2008-05-13 16:23:15 +080083{
84 char *xs = s;
Alek Dua24ea5c2009-05-26 09:56:47 +080085 size_t _count = count / 4;
86 unsigned long _c = c << 24 | c << 16 | c << 8 | c;
Sylvain Chouleur88c2e832015-02-27 13:59:16 +010087
Alek Dua24ea5c2009-05-26 09:56:47 +080088 while (_count--) {
89 *(long *)xs = _c;
90 xs += 4;
91 }
92 count %= 4;
Alek Dub7f7baf2008-05-13 16:23:15 +080093 while (count--)
Sylvain Chouleur88c2e832015-02-27 13:59:16 +010094 *xs++ = c;
Alek Dub7f7baf2008-05-13 16:23:15 +080095 return s;
96}
97
Alek Dud6f7f142008-05-14 16:59:04 +080098static size_t strnlen(const char *s, size_t maxlen)
99{
100 const char *es = s;
101 while (*es && maxlen) {
102 es++;
103 maxlen--;
104 }
105
106 return (es - s);
107}
108
Evgeny Kalugin8e8bf002013-10-24 11:21:07 +0300109static const char *strnchr(const char *s, int c, size_t maxlen)
110{
111 int i;
112 for (i = 0; i < maxlen && *s != c; s++, i++)
113 ;
114 return s;
115}
116
117int strncmp(const char *cs, const char *ct, size_t count)
118{
119 unsigned char c1, c2;
120
121 while (count) {
122 c1 = *cs++;
123 c2 = *ct++;
124 if (c1 != c2)
125 return c1 < c2 ? -1 : 1;
126 if (!c1)
127 break;
128 count--;
129 }
130 return 0;
131}
132
Florent Augerb5c97f52014-07-09 12:54:50 +0200133static inline int is_image_aosp(unsigned char *magic)
134{
135 return !strncmp((char *)magic, (char *)BOOT_MAGIC, sizeof(BOOT_MAGIC)-1);
136}
137
Alek Dub7f7baf2008-05-13 16:23:15 +0800138static void setup_boot_params(struct boot_params *bp, struct setup_header *sh)
139{
Alek Duacca6fb2008-06-02 14:19:57 +0800140 bp->screen_info.orig_video_mode = 0;
141 bp->screen_info.orig_video_lines = 0;
142 bp->screen_info.orig_video_cols = 0;
Alek Du07cd7e22008-05-22 16:36:16 +0800143 bp->alt_mem_k = 128*1024; // hard coded 128M mem here, since SFI will override it
Alek Du2c4ebec2008-05-13 16:56:23 +0800144 memcpy(&bp->hdr, sh, sizeof (struct setup_header));
Alek Du853e56b2008-05-16 16:44:31 +0800145 bp->hdr.type_of_loader = 0xff; //bootstub is unknown bootloader for kernel :)
Evgeny Kalugin8e8bf002013-10-24 11:21:07 +0300146 bp->hdr.hardware_subarch = X86_SUBARCH_MRST;
147}
148
149static u32 bzImage_setup(struct boot_params *bp, struct setup_header *sh)
150{
151 void *cmdline = (void *)BOOT_CMDLINE_OFFSET;
Florent Augerb5c97f52014-07-09 12:54:50 +0200152 struct boot_img_hdr *aosp = (struct boot_img_hdr *)AOSP_HEADER_ADDRESS;
Sylvain Chouleur88c2e832015-02-27 13:59:16 +0100153 size_t cmdline_len, extra_cmdline_len;
Florent Augerb5c97f52014-07-09 12:54:50 +0200154 u8 *initramfs, *ptr;
Evgeny Kalugin8e8bf002013-10-24 11:21:07 +0300155
Florent Augerb5c97f52014-07-09 12:54:50 +0200156 if (is_image_aosp(aosp->magic)) {
157 ptr = (u8*)aosp->kernel_addr;
158 cmdline_len = strnlen((const char *)aosp->cmdline, sizeof(aosp->cmdline));
Sylvain Chouleur88c2e832015-02-27 13:59:16 +0100159 extra_cmdline_len = strnlen((const char *)aosp->extra_cmdline, sizeof(aosp->extra_cmdline));
Evgeny Kalugin8e8bf002013-10-24 11:21:07 +0300160
Florent Augerb5c97f52014-07-09 12:54:50 +0200161 /*
Sylvain Chouleur88c2e832015-02-27 13:59:16 +0100162 * Copy the command + extra command line to be after bootparams
163 * so that it won't be overwritten by the kernel executable.
Florent Augerb5c97f52014-07-09 12:54:50 +0200164 */
Sylvain Chouleur88c2e832015-02-27 13:59:16 +0100165 memset(cmdline, 0, sizeof(aosp->cmdline) + sizeof(aosp->extra_cmdline));
Florent Augerb5c97f52014-07-09 12:54:50 +0200166 memcpy(cmdline, (const void *)aosp->cmdline, cmdline_len);
Sylvain Chouleur88c2e832015-02-27 13:59:16 +0100167 memcpy(cmdline + cmdline_len, (const void *)aosp->extra_cmdline, extra_cmdline_len);
Evgeny Kalugin8e8bf002013-10-24 11:21:07 +0300168
Florent Augerb5c97f52014-07-09 12:54:50 +0200169 bp->hdr.ramdisk_size = aosp->ramdisk_size;
170
171 initramfs = (u8 *)aosp->ramdisk_addr;
172 } else {
173 ptr = (u8*)BZIMAGE_OFFSET;
174 cmdline_len = strnlen((const char *)CMDLINE_OFFSET, CMDLINE_SIZE);
175 /*
176 * Copy the command line to be after bootparams so that it won't be
177 * overwritten by the kernel executable.
178 */
179 memset(cmdline, 0, CMDLINE_SIZE);
180 memcpy(cmdline, (const void *)CMDLINE_OFFSET, cmdline_len);
181
182 bp->hdr.ramdisk_size = *(u32 *)INITRD_SIZE_OFFSET;
183
184 initramfs = (u8 *)BZIMAGE_OFFSET + *(u32 *)BZIMAGE_SIZE_OFFSET;
185 }
Evgeny Kalugin8e8bf002013-10-24 11:21:07 +0300186
187 bp->hdr.cmd_line_ptr = BOOT_CMDLINE_OFFSET;
188 bp->hdr.cmdline_size = cmdline_len;
Sylvain Chouleur88c2e832015-02-27 13:59:16 +0100189#ifndef BUILD_RAMDUMP
Alek Du853e56b2008-05-16 16:44:31 +0800190 bp->hdr.ramdisk_image = (bp->alt_mem_k*1024 - bp->hdr.ramdisk_size) & 0xFFFFF000;
Evgeny Kalugin8e8bf002013-10-24 11:21:07 +0300191
Alek Du9843d272009-10-23 09:59:37 +0800192 if (*initramfs) {
193 bs_printk("Relocating initramfs to high memory ...\n");
194 memcpy((u8*)bp->hdr.ramdisk_image, initramfs, bp->hdr.ramdisk_size);
195 } else {
196 bs_printk("Won't relocate initramfs, are you in SLE?\n");
197 }
Sylvain Chouleur88c2e832015-02-27 13:59:16 +0100198#else
199 bp->hdr.ramdisk_image = (u32) initramfs;
200#endif
Evgeny Kalugin8e8bf002013-10-24 11:21:07 +0300201
202 while (1){
203 if (*(u32 *)ptr == SETUP_SIGNATURE && *(u32 *)(ptr+4) == 0)
204 break;
205 ptr++;
Bin Gao923fa8d2013-03-30 00:27:10 -0700206 }
Evgeny Kalugin8e8bf002013-10-24 11:21:07 +0300207 ptr+=4;
208 return (((unsigned int)ptr+511)/512)*512;
Alek Dub7f7baf2008-05-13 16:23:15 +0800209}
210
Jeremy Compostella36612702014-08-14 13:17:40 +0200211static inline void cpuid(u32 op, u32 regs[4])
Alek Dub7f7baf2008-05-13 16:23:15 +0800212{
Jeremy Compostella36612702014-08-14 13:17:40 +0200213 __asm__ volatile (
214 "mov %%ebx, %%edi\n"
215 "cpuid\n"
216 "xchg %%edi, %%ebx\n"
217 : "=a"(regs[0]), "=D"(regs[1]), "=c"(regs[2]), "=d"(regs[3])
218 : "a"(op)
219 );
Alek Du1e0485e2010-03-12 16:28:15 +0800220}
221
222enum cpuid_regs {
223 CR_EAX = 0,
224 CR_ECX,
225 CR_EDX,
226 CR_EBX
227};
228
Eric Ernstaecaba32013-04-02 12:02:59 -0700229int mid_identify_cpu(void)
Alek Du1e0485e2010-03-12 16:28:15 +0800230{
231 u32 regs[4];
232
Jeremy Compostella36612702014-08-14 13:17:40 +0200233 cpuid(1, regs);
Bin Gao8a13ab72013-03-30 00:11:07 -0700234
Eric Ernstaecaba32013-04-02 12:02:59 -0700235 switch ( regs[CR_EAX] & CPUID_MASK ) {
236
237 case PENWELL_FAMILY:
238 return MID_CPU_CHIP_PENWELL;
239 case CLOVERVIEW_FAMILY:
240 return MID_CPU_CHIP_CLOVERVIEW;
241 case VALLEYVIEW2_FAMILY:
242 return MID_CPU_CHIP_VALLEYVIEW2;
Mark F. Brown90847a82011-09-07 18:06:24 -0400243 case TANGIER_FAMILY:
244 return MID_CPU_CHIP_TANGIER;
245 case ANNIEDALE_FAMILY:
246 return MID_CPU_CHIP_ANNIEDALE;
Eric Ernstaecaba32013-04-02 12:02:59 -0700247 default:
248 return MID_CPU_CHIP_OTHER;
249 }
Alek Du1e0485e2010-03-12 16:28:15 +0800250}
251
252static void setup_spi(void)
253{
Leonard Mai4c56e452011-10-06 12:27:46 -0700254 if (!(*(int *)SPI_TYPE)) {
Eric Ernstaecaba32013-04-02 12:02:59 -0700255 switch ( mid_identify_cpu() ) {
256
257 case MID_CPU_CHIP_PENWELL:
258 *(int *)SPI_TYPE = SPI_1;
259 bs_printk("PNW detected\n");
260 break;
261
262 case MID_CPU_CHIP_CLOVERVIEW:
263 *(int *)SPI_TYPE = SPI_1;
264 bs_printk("CLV detected\n");
265 break;
266
Mark F. Brown90847a82011-09-07 18:06:24 -0400267 case MID_CPU_CHIP_TANGIER:
268 *(int *)SPI_TYPE = SPI_2;
269 bs_printk("MRD detected\n");
270 break;
271
272 case MID_CPU_CHIP_ANNIEDALE:
273 *(int *)SPI_TYPE = SPI_2;
274 bs_printk("ANN detected\n");
275 break;
276
Eric Ernstaecaba32013-04-02 12:02:59 -0700277 case MID_CPU_CHIP_VALLEYVIEW2:
278 case MID_CPU_CHIP_OTHER:
279 default:
280 no_uart_used = 1;
Alek Du1e0485e2010-03-12 16:28:15 +0800281 }
Leonard Mai4c56e452011-10-06 12:27:46 -0700282 }
Alek Du1e0485e2010-03-12 16:28:15 +0800283}
284
Evgeny Kalugin8e8bf002013-10-24 11:21:07 +0300285static void setup_gdt(void)
286{
287 static const u64 boot_gdt[] __attribute__((aligned(16))) = {
288 /* CS: code, read/execute, 4 GB, base 0 */
289 [GDT_ENTRY_BOOT_CS] = GDT_ENTRY(0xc09b, 0, 0xfffff),
290 /* DS: data, read/write, 4 GB, base 0 */
291 [GDT_ENTRY_BOOT_DS] = GDT_ENTRY(0xc093, 0, 0xfffff),
292 };
293 static struct gdt_ptr gdt;
294
295 gdt.len = sizeof(boot_gdt)-1;
296 gdt.ptr = (u32)&boot_gdt;
297
298 asm volatile("lgdtl %0" : : "m" (gdt));
299}
300
301static void setup_idt(void)
302{
303 static const struct gdt_ptr null_idt = {0, 0};
304 asm volatile("lidtl %0" : : "m" (null_idt));
305}
306
307static void vxe_fw_setup(void)
308{
309 u8 *vxe_fw_image;
310 u32 vxe_fw_size;
311 u32 vxe_fw_load_adrs;
312
313 vxe_fw_size = *(u32*)VXE_FW_SIZE_OFFSET;
314 /* do we have a VXE FW image? */
315 if (vxe_fw_size == 0)
316 return;
317
318 /* Do we have enough room to load the image? */
319 if (vxe_fw_size > imr6_toc.entries[IMR_TOC_ENTRY_VXE_FW].size) {
320 bs_printk("FATAL ERROR: VXE FW image size is too large for IMR\n");
321 FATAL_HANG();
322 }
323
324 vxe_fw_image = (u8 *)(
325 BZIMAGE_OFFSET
326 + *(u32 *)BZIMAGE_SIZE_OFFSET
327 + *(u32 *)INITRD_SIZE_OFFSET
328 );
329
330 vxe_fw_load_adrs = IMR6_START_ADDRESS + imr6_toc.entries[IMR_TOC_ENTRY_VXE_FW].start_offset;
331 memcpy((u8 *)vxe_fw_load_adrs, vxe_fw_image, vxe_fw_size);
332}
333
334static void load_imr_toc(u32 imr, u32 imrsize, imr_toc_t *toc, u32 tocsize)
335{
336 if (imr == 0 || imrsize == 0 || toc == NULL || tocsize == 0 || imrsize < tocsize )
337 {
338 bs_printk("FATAL ERROR: TOC size is too large for IMR\n");
339 FATAL_HANG();
340 }
341 memcpy((u8 *)imr, (u8 *)toc, tocsize);
342}
343
344
345static u32 xen_multiboot_setup(void)
346{
347 u32 *magic, *xen_image, i;
348 char *src, *dst;
349 u32 xen_size;
350 u32 xen_jump_adrs;
351 static module_t modules[3];
352 static multiboot_info_t mb = {
353 .flags = MBI_CMDLINE | MBI_MODULES | MBI_MEMMAP | MBI_DRIVES,
354 .mmap_addr = (u32)mb_mmap,
355 .mods_count = 3,
356 .mods_addr = (u32)modules,
357 };
358
359 xen_size = *(u32 *)XEN_SIZE_OFFSET;
360 /* do we have a xen image? */
361 if (xen_size == 0) {
362 return 0;
363 }
364
365 /* Compute the actual offset of the Xen image */
366 xen_image = (u32*)(
367 BZIMAGE_OFFSET
368 + *(u32 *)BZIMAGE_SIZE_OFFSET
369 + *(u32 *)INITRD_SIZE_OFFSET
370 + *(u32 *)VXE_FW_SIZE_OFFSET
371 + *(u32 *)SEC_PLAT_SVCS_SIZE_OFFSET
372 );
373
374 /* the multiboot signature should be located in the first 8192 bytes */
375 for (magic = xen_image; magic < xen_image + 2048; magic++)
376 if (*magic == MULTIBOOT_HEADER_MAGIC)
377 break;
378 if (*magic != MULTIBOOT_HEADER_MAGIC) {
379 return 0;
380 }
381
382 mb.cmdline = (u32)strnchr((char *)CMDLINE_OFFSET, '$', CMDLINE_SIZE) + 1;
Jeremy Compostella36612702014-08-14 13:17:40 +0200383 dst = (char *)mb.cmdline + strnlen((const char *)mb.cmdline, CMDLINE_SIZE) - 1;
Evgeny Kalugin8e8bf002013-10-24 11:21:07 +0300384 *dst = ' ';
385 dst++;
Jeremy Compostella36612702014-08-14 13:17:40 +0200386 src = (char *)CMDLINE_OFFSET;
Evgeny Kalugin8e8bf002013-10-24 11:21:07 +0300387 for (i = 0 ;i < strnlen((const char *)CMDLINE_OFFSET, CMDLINE_SIZE);i++) {
388 if (!strncmp(src, "capfreq=", 8)) {
389 while (*src != ' ' && *src != 0) {
390 *dst = *src;
391 dst++;
392 src++;
393 }
394 break;
395 }
396 src++;
397 }
398
399 /* fill in the multiboot module information: dom0 kernel + initrd + Platform Services Image */
400 modules[0].mod_start = BZIMAGE_OFFSET;
401 modules[0].mod_end = BZIMAGE_OFFSET + *(u32 *)BZIMAGE_SIZE_OFFSET;
402 modules[0].string = CMDLINE_OFFSET;
403
404 modules[1].mod_start = modules[0].mod_end ;
405 modules[1].mod_end = modules[1].mod_start + *(u32 *)INITRD_SIZE_OFFSET;
406 modules[1].string = 0;
407
408 modules[2].mod_start = sps_load_adrs;
409 modules[2].mod_end = modules[2].mod_start + *(u32 *)SEC_PLAT_SVCS_SIZE_OFFSET;
410 modules[2].string = 0;
411
412 mb.drives_addr = IMR6_START_ADDRESS + imr6_toc.entries[IMR_TOC_ENTRY_XEN_EXTRA].start_offset;
413 mb.drives_length = imr6_toc.entries[IMR_TOC_ENTRY_XEN_EXTRA].size;
414
415 for(i = 0; i < E820MAX; i++)
416 if (!mb_mmap[i].size)
417 break;
418 mb.mmap_length = i * sizeof(memory_map_t);
419
420 /* relocate xen to start address */
421 if (xen_size > imr7_size) {
422 bs_printk("FATAL ERROR: Xen image size is too large for IMR\n");
423 FATAL_HANG();
424 }
425 xen_jump_adrs = IMR7_START_ADDRESS;
426 memcpy((u8 *)xen_jump_adrs, xen_image, xen_size);
427
428 mb_info = (u32)&mb;
429 mb_magic = MULTIBOOT_BOOTLOADER_MAGIC;
430
431 return (u32)xen_jump_adrs;
432}
433
434static void sec_plat_svcs_setup(void)
435{
436 u8 *sps_image;
437 u32 sps_size;
438
439 sps_size = PAGE_ALIGN_FWD(*(u32*)SEC_PLAT_SVCS_SIZE_OFFSET);
440 /* do we have a SPS image? */
441 if (sps_size == 0)
442 return;
443
444 /* Do we have enough room to load the image? */
445 if (sps_size > imr7_size) {
446 bs_printk("FATAL ERROR: SPS image size is too large for IMR\n");
447 FATAL_HANG();
448 }
449
450 sps_image = (u8 *)(
451 BZIMAGE_OFFSET
452 + *(u32 *)BZIMAGE_SIZE_OFFSET
453 + *(u32 *)INITRD_SIZE_OFFSET
454 + *(u32 *)VXE_FW_SIZE_OFFSET
455 );
456
457 /* load SPS image (with assumed CHAABI Mailboxes suffixed) */
458 /* at bottom of IMR7 */
459 /* Must be page-aligned or Xen will panic */
460 sps_load_adrs = PAGE_ALIGN_BACK(IMR7_START_ADDRESS + imr7_size - sps_size);
461 memcpy((u8 *)sps_load_adrs, sps_image, sps_size);
462
463 /* reduce remaining size for Xen image size check */
464 imr7_size -= sps_size;
465}
466
Alek Du6135ebb2008-05-20 14:07:07 +0800467int bootstub(void)
Alek Dub7f7baf2008-05-13 16:23:15 +0800468{
Evgeny Kalugin8e8bf002013-10-24 11:21:07 +0300469 u32 jmp;
Florent Augerb5c97f52014-07-09 12:54:50 +0200470 struct boot_img_hdr *aosp = (struct boot_img_hdr *)AOSP_HEADER_ADDRESS;
Evgeny Kalugin8e8bf002013-10-24 11:21:07 +0300471 struct boot_params *bp = (struct boot_params *)BOOT_PARAMS_OFFSET;
Florent Augerb5c97f52014-07-09 12:54:50 +0200472 struct setup_header *sh;
Evgeny Kalugin8e8bf002013-10-24 11:21:07 +0300473 u32 imr_size;
474 int nr_entries;
475
Florent Augerb5c97f52014-07-09 12:54:50 +0200476 if (is_image_aosp(aosp->magic)) {
Sylvain Chouleur88c2e832015-02-27 13:59:16 +0100477 sh = (struct setup_header *)((unsigned int)aosp->kernel_addr + \
478 (unsigned int)offsetof(struct boot_params,hdr));
Florent Augerb5c97f52014-07-09 12:54:50 +0200479 /* disable the bs_printk through SPI/UART */
480 *(int *)SPI_UART_SUPPRESSION = 1;
481 *(int *)SPI_TYPE = SPI_2;
482 } else
483 sh = (struct setup_header *)SETUP_HEADER_OFFSET;
484
485 setup_idt();
Evgeny Kalugin8e8bf002013-10-24 11:21:07 +0300486 setup_gdt();
Alek Du1e0485e2010-03-12 16:28:15 +0800487 setup_spi();
Florent Augerb5c97f52014-07-09 12:54:50 +0200488 bs_printk("Bootstub Version: 1.4 ...\n");
Evgeny Kalugin8e8bf002013-10-24 11:21:07 +0300489
490 memset(bp, 0, sizeof (struct boot_params));
491
492 if (mid_identify_cpu() == MID_CPU_CHIP_VALLEYVIEW2) {
493 nr_entries = get_e820_by_bios(bp->e820_map);
494 bp->e820_entries = (nr_entries > 0) ? nr_entries : 0;
495 } else {
496 sfi_setup_mmap(bp, mb_mmap);
497 }
498
Evgeny Kalugin9b26e972014-01-03 00:16:48 +0200499 if ((mid_identify_cpu() != MID_CPU_CHIP_TANGIER) && (mid_identify_cpu() != MID_CPU_CHIP_ANNIEDALE)) {
Evgeny Kalugin8e8bf002013-10-24 11:21:07 +0300500 if ((IMR6_END_ADDRESS > IMR6_START_ADDRESS) && (IMR7_END_ADDRESS > IMR7_START_ADDRESS)) {
501 imr_size = PAGE_ALIGN_FWD(IMR6_END_ADDRESS - IMR6_START_ADDRESS);
502 load_imr_toc(IMR6_START_ADDRESS, imr_size, &imr6_toc, sizeof(imr6_toc));
503 vxe_fw_setup();
504 sfi_add_e820_entry(bp, mb_mmap, IMR6_START_ADDRESS, imr_size, E820_RESERVED);
505
506 imr7_size = PAGE_ALIGN_FWD(IMR7_END_ADDRESS - IMR7_START_ADDRESS);
507 sec_plat_svcs_setup();
508 sfi_add_e820_entry(bp, mb_mmap, IMR7_START_ADDRESS, imr7_size, E820_RESERVED);
509 } else {
510 *(u32 *)XEN_SIZE_OFFSET = 0; /* Don't allow Xen to boot */
511 }
512 } else {
513 *(u32 *)XEN_SIZE_OFFSET = 0; /* Don't allow Xen to boot */
514 }
515
516 setup_boot_params(bp, sh);
517
518 jmp = xen_multiboot_setup();
519 if (!jmp) {
520 bs_printk("Using bzImage to boot\n");
521 jmp = bzImage_setup(bp, sh);
522 } else
523 bs_printk("Using multiboot image to boot\n");
524
525 bs_printk("Jump to kernel 32bit entry\n");
526 return jmp;
Alek Dub7f7baf2008-05-13 16:23:15 +0800527}
Mark F. Brown90847a82011-09-07 18:06:24 -0400528
529void bs_printk(const char *str)
530{
Evgeny Kalugin8e8bf002013-10-24 11:21:07 +0300531 if (*(int *)SPI_UART_SUPPRESSION)
532 return;
Mark F. Brown90847a82011-09-07 18:06:24 -0400533
Evgeny Kalugin8e8bf002013-10-24 11:21:07 +0300534 switch (*(int *)SPI_TYPE) {
Mark F. Brown90847a82011-09-07 18:06:24 -0400535
Evgeny Kalugin8e8bf002013-10-24 11:21:07 +0300536 case SPI_1:
Mark F. Brown90847a82011-09-07 18:06:24 -0400537 bs_spi_printk(str);
538 break;
539
540 case SPI_2:
541 bs_ssp_printk(str);
542 break;
Evgeny Kalugin8e8bf002013-10-24 11:21:07 +0300543 }
Mark F. Brown90847a82011-09-07 18:06:24 -0400544}