ppc64: Don't set Kp bit on SLB
[openbios.git] / arch / sparc64 / multiboot.c
blob8514ca0a48d6d456a66c9ac55c84e946d6771289
1 /* Support for Multiboot */
3 #include "config.h"
4 #include "asm/io.h"
5 #include "libopenbios/sys_info.h"
6 #include "multiboot.h"
8 #define printf printk
9 #ifdef CONFIG_DEBUG_BOOT
10 #define debug printk
11 #else
12 #define debug(x...)
13 #endif
15 struct mbheader {
16 unsigned int magic, flags, checksum;
18 const struct mbheader multiboot_header
19 __attribute__((section (".hdr"))) =
21 MULTIBOOT_HEADER_MAGIC,
22 MULTIBOOT_HEADER_FLAGS,
23 -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
26 /* Multiboot information structure, provided by loader to us */
28 struct multiboot_mmap {
29 unsigned entry_size;
30 unsigned base_lo, base_hi;
31 unsigned size_lo, size_hi;
32 unsigned type;
35 #define MULTIBOOT_MEM_VALID 0x01
36 #define MULTIBOOT_BOOT_DEV_VALID 0x02
37 #define MULTIBOOT_CMDLINE_VALID 0x04
38 #define MULTIBOOT_MODS_VALID 0x08
39 #define MULTIBOOT_AOUT_SYMS_VALID 0x10
40 #define MULTIBOOT_ELF_SYMS_VALID 0x20
41 #define MULTIBOOT_MMAP_VALID 0x40
43 void collect_multiboot_info(struct sys_info *info);
44 void collect_multiboot_info(struct sys_info *info)
46 struct multiboot_info *mbinfo;
47 struct multiboot_mmap *mbmem;
48 unsigned mbcount, mbaddr;
49 unsigned int i;
50 struct memrange *mmap;
51 int mmap_count;
52 module_t *mod;
54 if (info->boot_type != 0x2BADB002)
55 return;
57 debug("Using Multiboot information at %#lx\n", info->boot_data);
59 mbinfo = phys_to_virt(info->boot_data);
61 if (mbinfo->mods_count != 1) {
62 printf("Multiboot: no dictionary\n");
63 return;
66 mod = (module_t *) mbinfo->mods_addr;
67 info->dict_start=(unsigned long *)mod->mod_start;
68 info->dict_end=(unsigned long *)mod->mod_end;
70 if (mbinfo->flags & MULTIBOOT_MMAP_VALID) {
71 /* convert mmap records */
72 mbmem = phys_to_virt(mbinfo->mmap_addr);
73 mbcount = mbinfo->mmap_length / (mbmem->entry_size + 4);
74 mmap = malloc(mbcount * sizeof(struct memrange));
75 mmap_count = 0;
76 mbaddr = mbinfo->mmap_addr;
77 for (i = 0; i < mbcount; i++) {
78 mbmem = phys_to_virt(mbaddr);
79 debug("%08x%08x %08x%08x (%d)\n",
80 mbmem->base_hi,
81 mbmem->base_lo,
82 mbmem->size_hi,
83 mbmem->size_lo,
84 mbmem->type);
85 if (mbmem->type == 1) { /* Only normal RAM */
86 mmap[mmap_count].base = mbmem->base_lo
87 + (((unsigned long long) mbmem->base_hi) << 32);
88 mmap[mmap_count].size = mbmem->size_lo
89 + (((unsigned long long) mbmem->size_hi) << 32);
90 mmap_count++;
92 mbaddr += mbmem->entry_size + 4;
93 if (mbaddr >= mbinfo->mmap_addr + mbinfo->mmap_length)
94 break;
96 /* simple sanity check - there should be at least 2 RAM segments
97 * (base 640k and extended) */
98 if (mmap_count >= 2)
99 goto got_it;
101 printf("Multiboot mmap is broken\n");
102 free(mmap);
103 /* fall back to mem_lower/mem_upper */
106 if (mbinfo->flags & MULTIBOOT_MEM_VALID) {
107 /* use mem_lower and mem_upper */
108 mmap_count = 2;
109 mmap = malloc(2 * sizeof(*mmap));
110 mmap[0].base = 0;
111 mmap[0].size = mbinfo->mem_lower << 10;
112 mmap[1].base = 1 << 20; /* 1MB */
113 mmap[1].size = mbinfo->mem_upper << 10;
114 goto got_it;
117 printf("Can't get memory information from Multiboot\n");
118 return;
120 got_it:
121 info->memrange = mmap;
122 info->n_memranges = mmap_count;
124 return;