1.26.4
by Colin Watson
Import upstream version 1.99~20101122 |
1 |
/* linux.c - boot Linux */
|
2 |
/*
|
|
3 |
* GRUB -- GRand Unified Bootloader
|
|
4 |
* Copyright (C) 2003, 2004, 2005, 2007, 2009 Free Software Foundation, Inc.
|
|
5 |
*
|
|
6 |
* GRUB is free software: you can redistribute it and/or modify
|
|
7 |
* it under the terms of the GNU General Public License as published by
|
|
8 |
* the Free Software Foundation, either version 3 of the License, or
|
|
9 |
* (at your option) any later version.
|
|
10 |
*
|
|
11 |
* GRUB is distributed in the hope that it will be useful,
|
|
12 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14 |
* GNU General Public License for more details.
|
|
15 |
*
|
|
16 |
* You should have received a copy of the GNU General Public License
|
|
17 |
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
|
18 |
*/
|
|
19 |
||
20 |
#include <grub/elf.h> |
|
21 |
#include <grub/elfload.h> |
|
22 |
#include <grub/loader.h> |
|
23 |
#include <grub/dl.h> |
|
24 |
#include <grub/mm.h> |
|
25 |
#include <grub/misc.h> |
|
26 |
#include <grub/ieee1275/ieee1275.h> |
|
27 |
#include <grub/command.h> |
|
28 |
#include <grub/i18n.h> |
|
29 |
#include <grub/memory.h> |
|
1.17.12
by Colin Watson
Import upstream version 1.99~20110111 |
30 |
#include <grub/lib/cmdline.h> |
1.17.17
by Colin Watson
Import upstream version 2.00+20131208 |
31 |
#include <grub/linux.h> |
1.26.4
by Colin Watson
Import upstream version 1.99~20101122 |
32 |
|
1.17.15
by Colin Watson
Import upstream version 1.99 |
33 |
GRUB_MOD_LICENSE ("GPLv3+"); |
34 |
||
1.26.4
by Colin Watson
Import upstream version 1.99~20101122 |
35 |
static grub_dl_t my_mod; |
36 |
||
37 |
static int loaded; |
|
38 |
||
39 |
/* /virtual-memory/translations property layout */
|
|
40 |
struct grub_ieee1275_translation { |
|
41 |
grub_uint64_t vaddr; |
|
42 |
grub_uint64_t size; |
|
43 |
grub_uint64_t data; |
|
44 |
};
|
|
45 |
||
46 |
static struct grub_ieee1275_translation *of_trans; |
|
47 |
static int of_num_trans; |
|
48 |
||
49 |
static grub_addr_t phys_base; |
|
50 |
static grub_addr_t grub_phys_start; |
|
51 |
static grub_addr_t grub_phys_end; |
|
52 |
||
53 |
static grub_addr_t initrd_addr; |
|
54 |
static grub_addr_t initrd_paddr; |
|
55 |
static grub_size_t initrd_size; |
|
56 |
||
57 |
static Elf64_Addr linux_entry; |
|
58 |
static grub_addr_t linux_addr; |
|
59 |
static grub_addr_t linux_paddr; |
|
60 |
static grub_size_t linux_size; |
|
61 |
||
62 |
static char *linux_args; |
|
63 |
||
64 |
struct linux_bootstr_info { |
|
65 |
int len, valid; |
|
66 |
char buf[]; |
|
67 |
};
|
|
68 |
||
69 |
struct linux_hdrs { |
|
70 |
/* All HdrS versions support these fields. */
|
|
71 |
unsigned int start_insns[2]; |
|
72 |
char magic[4]; /* "HdrS" */ |
|
73 |
unsigned int linux_kernel_version; /* LINUX_VERSION_CODE */ |
|
74 |
unsigned short hdrs_version; |
|
75 |
unsigned short root_flags; |
|
76 |
unsigned short root_dev; |
|
77 |
unsigned short ram_flags; |
|
78 |
unsigned int __deprecated_ramdisk_image; |
|
79 |
unsigned int ramdisk_size; |
|
80 |
||
81 |
/* HdrS versions 0x0201 and higher only */
|
|
82 |
char *reboot_command; |
|
83 |
||
84 |
/* HdrS versions 0x0202 and higher only */
|
|
85 |
struct linux_bootstr_info *bootstr_info; |
|
86 |
||
87 |
/* HdrS versions 0x0301 and higher only */
|
|
88 |
unsigned long ramdisk_image; |
|
89 |
};
|
|
90 |
||
91 |
static grub_err_t |
|
92 |
grub_linux_boot (void) |
|
93 |
{
|
|
94 |
struct linux_bootstr_info *bp; |
|
95 |
struct linux_hdrs *hp; |
|
96 |
grub_addr_t addr; |
|
97 |
||
98 |
hp = (struct linux_hdrs *) linux_addr; |
|
99 |
||
100 |
/* Any pointer we dereference in the kernel image must be relocated
|
|
101 |
to where we actually loaded the kernel. */
|
|
102 |
addr = (grub_addr_t) hp->bootstr_info; |
|
103 |
addr += (linux_addr - linux_entry); |
|
104 |
bp = (struct linux_bootstr_info *) addr; |
|
105 |
||
106 |
/* Set the command line arguments, unless the kernel has been
|
|
107 |
built with a fixed CONFIG_CMDLINE. */
|
|
108 |
if (!bp->valid) |
|
109 |
{
|
|
110 |
int len = grub_strlen (linux_args) + 1; |
|
111 |
if (bp->len < len) |
|
112 |
len = bp->len; |
|
113 |
memcpy(bp->buf, linux_args, len); |
|
114 |
bp->buf[len-1] = '\0'; |
|
115 |
bp->valid = 1; |
|
116 |
}
|
|
117 |
||
118 |
if (initrd_addr) |
|
119 |
{
|
|
120 |
/* The kernel expects the physical address, adjusted relative
|
|
121 |
to the lowest address advertised in "/memory"'s available
|
|
122 |
property.
|
|
123 |
||
124 |
The history of this is that back when the kernel only supported
|
|
125 |
specifying a 32-bit ramdisk address, this was the way to still
|
|
126 |
be able to specify the ramdisk physical address even if memory
|
|
127 |
started at some place above 4GB.
|
|
128 |
||
129 |
The magic 0x400000 is KERNBASE, I have no idea why SILO adds
|
|
130 |
that term into the address, but it does and thus we have to do
|
|
131 |
it too as this is what the kernel expects. */
|
|
132 |
hp->ramdisk_image = initrd_paddr - phys_base + 0x400000; |
|
133 |
hp->ramdisk_size = initrd_size; |
|
134 |
}
|
|
135 |
||
136 |
grub_dprintf ("loader", "Entry point: 0x%lx\n", linux_addr); |
|
137 |
grub_dprintf ("loader", "Initrd at: 0x%lx, size 0x%lx\n", initrd_addr, |
|
138 |
initrd_size); |
|
139 |
grub_dprintf ("loader", "Boot arguments: %s\n", linux_args); |
|
140 |
grub_dprintf ("loader", "Jumping to Linux...\n"); |
|
141 |
||
142 |
/* Boot the kernel. */
|
|
143 |
asm volatile ("sethi %hi(grub_ieee1275_entry_fn), %o1\n" |
|
144 |
"ldx [%o1 + %lo(grub_ieee1275_entry_fn)], %o4\n" |
|
145 |
"sethi %hi(grub_ieee1275_original_stack), %o1\n" |
|
146 |
"ldx [%o1 + %lo(grub_ieee1275_original_stack)], %o6\n" |
|
147 |
"sethi %hi(linux_addr), %o1\n" |
|
148 |
"ldx [%o1 + %lo(linux_addr)], %o5\n" |
|
149 |
"mov %g0, %o0\n" |
|
150 |
"mov %g0, %o2\n" |
|
151 |
"mov %g0, %o3\n" |
|
152 |
"jmp %o5\n" |
|
153 |
"mov %g0, %o1\n"); |
|
154 |
||
155 |
return GRUB_ERR_NONE; |
|
156 |
}
|
|
157 |
||
158 |
static grub_err_t |
|
159 |
grub_linux_release_mem (void) |
|
160 |
{
|
|
161 |
grub_free (linux_args); |
|
162 |
linux_args = 0; |
|
163 |
linux_addr = 0; |
|
164 |
initrd_addr = 0; |
|
165 |
||
166 |
return GRUB_ERR_NONE; |
|
167 |
}
|
|
168 |
||
169 |
static grub_err_t |
|
170 |
grub_linux_unload (void) |
|
171 |
{
|
|
172 |
grub_err_t err; |
|
173 |
||
174 |
err = grub_linux_release_mem (); |
|
175 |
grub_dl_unref (my_mod); |
|
176 |
||
177 |
loaded = 0; |
|
178 |
||
179 |
return err; |
|
180 |
}
|
|
181 |
||
182 |
#define FOUR_MB (4 * 1024 * 1024)
|
|
183 |
||
1.17.17
by Colin Watson
Import upstream version 2.00+20131208 |
184 |
/* Context for alloc_phys. */
|
185 |
struct alloc_phys_ctx |
|
186 |
{
|
|
187 |
grub_addr_t size; |
|
188 |
grub_addr_t ret; |
|
189 |
};
|
|
190 |
||
191 |
/* Helper for alloc_phys. */
|
|
192 |
static int |
|
193 |
alloc_phys_choose (grub_uint64_t addr, grub_uint64_t len, |
|
194 |
grub_memory_type_t type, void *data) |
|
195 |
{
|
|
196 |
struct alloc_phys_ctx *ctx = data; |
|
197 |
grub_addr_t end = addr + len; |
|
198 |
||
199 |
if (type != 1) |
|
200 |
return 0; |
|
201 |
||
202 |
addr = ALIGN_UP (addr, FOUR_MB); |
|
203 |
if (addr + ctx->size >= end) |
|
204 |
return 0; |
|
205 |
||
206 |
if (addr >= grub_phys_start && addr < grub_phys_end) |
|
207 |
{
|
|
208 |
addr = ALIGN_UP (grub_phys_end, FOUR_MB); |
|
209 |
if (addr + ctx->size >= end) |
|
210 |
return 0; |
|
211 |
}
|
|
212 |
if ((addr + ctx->size) >= grub_phys_start |
|
213 |
&& (addr + ctx->size) < grub_phys_end) |
|
214 |
{
|
|
215 |
addr = ALIGN_UP (grub_phys_end, FOUR_MB); |
|
216 |
if (addr + ctx->size >= end) |
|
217 |
return 0; |
|
218 |
}
|
|
219 |
||
220 |
if (loaded) |
|
221 |
{
|
|
222 |
grub_addr_t linux_end = ALIGN_UP (linux_paddr + linux_size, FOUR_MB); |
|
223 |
||
224 |
if (addr >= linux_paddr && addr < linux_end) |
|
225 |
{
|
|
226 |
addr = linux_end; |
|
227 |
if (addr + ctx->size >= end) |
|
228 |
return 0; |
|
229 |
}
|
|
230 |
if ((addr + ctx->size) >= linux_paddr |
|
231 |
&& (addr + ctx->size) < linux_end) |
|
232 |
{
|
|
233 |
addr = linux_end; |
|
234 |
if (addr + ctx->size >= end) |
|
235 |
return 0; |
|
236 |
}
|
|
237 |
}
|
|
238 |
||
239 |
ctx->ret = addr; |
|
240 |
return 1; |
|
241 |
}
|
|
242 |
||
1.26.4
by Colin Watson
Import upstream version 1.99~20101122 |
243 |
static grub_addr_t |
244 |
alloc_phys (grub_addr_t size) |
|
245 |
{
|
|
1.17.17
by Colin Watson
Import upstream version 2.00+20131208 |
246 |
struct alloc_phys_ctx ctx = { |
247 |
.size = size, |
|
248 |
.ret = (grub_addr_t) -1 |
|
249 |
};
|
|
250 |
||
251 |
grub_machine_mmap_iterate (alloc_phys_choose, &ctx); |
|
252 |
||
253 |
return ctx.ret; |
|
1.26.4
by Colin Watson
Import upstream version 1.99~20101122 |
254 |
}
|
255 |
||
256 |
static grub_err_t |
|
1.17.16
by Colin Watson
Import upstream version 2.00 |
257 |
grub_linux_load64 (grub_elf_t elf, const char *filename) |
1.26.4
by Colin Watson
Import upstream version 1.99~20101122 |
258 |
{
|
259 |
grub_addr_t off, paddr, base; |
|
260 |
int ret; |
|
261 |
||
262 |
linux_entry = elf->ehdr.ehdr64.e_entry; |
|
263 |
linux_addr = 0x40004000; |
|
264 |
off = 0x4000; |
|
1.17.17
by Colin Watson
Import upstream version 2.00+20131208 |
265 |
linux_size = grub_elf64_size (elf, 0, 0); |
1.26.4
by Colin Watson
Import upstream version 1.99~20101122 |
266 |
if (linux_size == 0) |
267 |
return grub_errno; |
|
268 |
||
269 |
grub_dprintf ("loader", "Attempting to claim at 0x%lx, size 0x%lx.\n", |
|
270 |
linux_addr, linux_size); |
|
271 |
||
272 |
paddr = alloc_phys (linux_size + off); |
|
273 |
if (paddr == (grub_addr_t) -1) |
|
274 |
return grub_error (GRUB_ERR_OUT_OF_MEMORY, |
|
275 |
"couldn't allocate physical memory"); |
|
276 |
ret = grub_ieee1275_map (paddr, linux_addr - off, |
|
277 |
linux_size + off, IEEE1275_MAP_DEFAULT); |
|
278 |
if (ret) |
|
279 |
return grub_error (GRUB_ERR_OUT_OF_MEMORY, |
|
280 |
"couldn't map physical memory"); |
|
281 |
||
282 |
grub_dprintf ("loader", "Loading Linux at vaddr 0x%lx, paddr 0x%lx, size 0x%lx\n", |
|
283 |
linux_addr, paddr, linux_size); |
|
284 |
||
285 |
linux_paddr = paddr; |
|
286 |
||
287 |
base = linux_entry - off; |
|
288 |
||
289 |
/* Now load the segments into the area we claimed. */
|
|
1.17.17
by Colin Watson
Import upstream version 2.00+20131208 |
290 |
return grub_elf64_load (elf, filename, (void *) (linux_addr - off - base), GRUB_ELF_LOAD_FLAGS_NONE, 0, 0); |
1.26.4
by Colin Watson
Import upstream version 1.99~20101122 |
291 |
}
|
292 |
||
293 |
static grub_err_t |
|
294 |
grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), |
|
295 |
int argc, char *argv[]) |
|
296 |
{
|
|
297 |
grub_file_t file = 0; |
|
298 |
grub_elf_t elf = 0; |
|
299 |
int size; |
|
300 |
||
301 |
grub_dl_ref (my_mod); |
|
302 |
||
303 |
if (argc == 0) |
|
304 |
{
|
|
1.17.16
by Colin Watson
Import upstream version 2.00 |
305 |
grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); |
1.26.4
by Colin Watson
Import upstream version 1.99~20101122 |
306 |
goto out; |
307 |
}
|
|
308 |
||
309 |
file = grub_file_open (argv[0]); |
|
310 |
if (!file) |
|
311 |
goto out; |
|
312 |
||
1.17.16
by Colin Watson
Import upstream version 2.00 |
313 |
elf = grub_elf_file (file, argv[0]); |
1.26.4
by Colin Watson
Import upstream version 1.99~20101122 |
314 |
if (! elf) |
315 |
goto out; |
|
316 |
||
317 |
if (elf->ehdr.ehdr32.e_type != ET_EXEC) |
|
318 |
{
|
|
319 |
grub_error (GRUB_ERR_UNKNOWN_OS, |
|
1.17.16
by Colin Watson
Import upstream version 2.00 |
320 |
N_("this ELF file is not of the right type")); |
1.26.4
by Colin Watson
Import upstream version 1.99~20101122 |
321 |
goto out; |
322 |
}
|
|
323 |
||
324 |
/* Release the previously used memory. */
|
|
325 |
grub_loader_unset (); |
|
326 |
||
327 |
if (grub_elf_is_elf64 (elf)) |
|
1.17.16
by Colin Watson
Import upstream version 2.00 |
328 |
grub_linux_load64 (elf, argv[0]); |
1.26.4
by Colin Watson
Import upstream version 1.99~20101122 |
329 |
else
|
330 |
{
|
|
1.17.16
by Colin Watson
Import upstream version 2.00 |
331 |
grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("invalid arch-dependent ELF magic")); |
1.26.4
by Colin Watson
Import upstream version 1.99~20101122 |
332 |
goto out; |
333 |
}
|
|
334 |
||
1.17.12
by Colin Watson
Import upstream version 1.99~20110111 |
335 |
size = grub_loader_cmdline_size(argc, argv); |
1.26.4
by Colin Watson
Import upstream version 1.99~20101122 |
336 |
|
1.17.12
by Colin Watson
Import upstream version 1.99~20110111 |
337 |
linux_args = grub_malloc (size + sizeof (LINUX_IMAGE)); |
1.26.4
by Colin Watson
Import upstream version 1.99~20101122 |
338 |
if (! linux_args) |
339 |
goto out; |
|
340 |
||
1.17.12
by Colin Watson
Import upstream version 1.99~20110111 |
341 |
/* Create kernel command line. */
|
342 |
grub_memcpy (linux_args, LINUX_IMAGE, sizeof (LINUX_IMAGE)); |
|
343 |
grub_create_loader_cmdline (argc, argv, linux_args + sizeof (LINUX_IMAGE) - 1, |
|
344 |
size); |
|
1.26.4
by Colin Watson
Import upstream version 1.99~20101122 |
345 |
|
346 |
out: |
|
347 |
if (elf) |
|
348 |
grub_elf_close (elf); |
|
349 |
else if (file) |
|
350 |
grub_file_close (file); |
|
351 |
||
352 |
if (grub_errno != GRUB_ERR_NONE) |
|
353 |
{
|
|
354 |
grub_linux_release_mem (); |
|
355 |
grub_dl_unref (my_mod); |
|
356 |
loaded = 0; |
|
357 |
}
|
|
358 |
else
|
|
359 |
{
|
|
360 |
grub_loader_set (grub_linux_boot, grub_linux_unload, 1); |
|
361 |
initrd_addr = 0; |
|
362 |
loaded = 1; |
|
363 |
}
|
|
364 |
||
365 |
return grub_errno; |
|
366 |
}
|
|
367 |
||
368 |
static grub_err_t |
|
369 |
grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), |
|
370 |
int argc, char *argv[]) |
|
371 |
{
|
|
1.17.16
by Colin Watson
Import upstream version 2.00 |
372 |
grub_size_t size = 0; |
1.26.4
by Colin Watson
Import upstream version 1.99~20101122 |
373 |
grub_addr_t paddr; |
374 |
grub_addr_t addr; |
|
375 |
int ret; |
|
1.17.17
by Colin Watson
Import upstream version 2.00+20131208 |
376 |
struct grub_linux_initrd_context initrd_ctx; |
1.26.4
by Colin Watson
Import upstream version 1.99~20101122 |
377 |
|
378 |
if (argc == 0) |
|
379 |
{
|
|
1.17.16
by Colin Watson
Import upstream version 2.00 |
380 |
grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); |
1.26.4
by Colin Watson
Import upstream version 1.99~20101122 |
381 |
goto fail; |
382 |
}
|
|
383 |
||
384 |
if (!loaded) |
|
385 |
{
|
|
1.17.16
by Colin Watson
Import upstream version 2.00 |
386 |
grub_error (GRUB_ERR_BAD_ARGUMENT, N_("you need to load the kernel first")); |
1.26.4
by Colin Watson
Import upstream version 1.99~20101122 |
387 |
goto fail; |
388 |
}
|
|
389 |
||
1.17.17
by Colin Watson
Import upstream version 2.00+20131208 |
390 |
if (grub_initrd_init (argc, argv, &initrd_ctx)) |
1.26.4
by Colin Watson
Import upstream version 1.99~20101122 |
391 |
goto fail; |
392 |
||
1.17.17
by Colin Watson
Import upstream version 2.00+20131208 |
393 |
size = grub_get_initrd_size (&initrd_ctx); |
1.17.16
by Colin Watson
Import upstream version 2.00 |
394 |
|
1.26.4
by Colin Watson
Import upstream version 1.99~20101122 |
395 |
addr = 0x60000000; |
396 |
||
397 |
paddr = alloc_phys (size); |
|
398 |
if (paddr == (grub_addr_t) -1) |
|
399 |
{
|
|
400 |
grub_error (GRUB_ERR_OUT_OF_MEMORY, |
|
401 |
"couldn't allocate physical memory"); |
|
402 |
goto fail; |
|
403 |
}
|
|
404 |
ret = grub_ieee1275_map (paddr, addr, size, IEEE1275_MAP_DEFAULT); |
|
405 |
if (ret) |
|
406 |
{
|
|
407 |
grub_error (GRUB_ERR_OUT_OF_MEMORY, |
|
408 |
"couldn't map physical memory"); |
|
409 |
goto fail; |
|
410 |
}
|
|
411 |
||
412 |
grub_dprintf ("loader", "Loading initrd at vaddr 0x%lx, paddr 0x%lx, size 0x%lx\n", |
|
413 |
addr, paddr, size); |
|
414 |
||
1.17.17
by Colin Watson
Import upstream version 2.00+20131208 |
415 |
if (grub_initrd_load (&initrd_ctx, argv, (void *) addr)) |
416 |
goto fail; |
|
1.26.4
by Colin Watson
Import upstream version 1.99~20101122 |
417 |
|
418 |
initrd_addr = addr; |
|
419 |
initrd_paddr = paddr; |
|
420 |
initrd_size = size; |
|
421 |
||
422 |
fail: |
|
1.17.17
by Colin Watson
Import upstream version 2.00+20131208 |
423 |
grub_initrd_close (&initrd_ctx); |
1.26.4
by Colin Watson
Import upstream version 1.99~20101122 |
424 |
|
425 |
return grub_errno; |
|
426 |
}
|
|
427 |
||
1.17.17
by Colin Watson
Import upstream version 2.00+20131208 |
428 |
/* Helper for determine_phys_base. */
|
429 |
static int |
|
430 |
get_physbase (grub_uint64_t addr, grub_uint64_t len __attribute__ ((unused)), |
|
431 |
grub_memory_type_t type, void *data __attribute__ ((unused))) |
|
432 |
{
|
|
433 |
if (type != 1) |
|
434 |
return 0; |
|
435 |
if (addr < phys_base) |
|
436 |
phys_base = addr; |
|
437 |
return 0; |
|
438 |
}
|
|
439 |
||
1.26.4
by Colin Watson
Import upstream version 1.99~20101122 |
440 |
static void |
441 |
determine_phys_base (void) |
|
442 |
{
|
|
443 |
phys_base = ~(grub_uint64_t) 0; |
|
1.17.17
by Colin Watson
Import upstream version 2.00+20131208 |
444 |
grub_machine_mmap_iterate (get_physbase, NULL); |
1.26.4
by Colin Watson
Import upstream version 1.99~20101122 |
445 |
}
|
446 |
||
447 |
static void |
|
448 |
fetch_translations (void) |
|
449 |
{
|
|
450 |
grub_ieee1275_phandle_t node; |
|
451 |
grub_ssize_t actual; |
|
452 |
int i; |
|
453 |
||
454 |
if (grub_ieee1275_finddevice ("/virtual-memory", &node)) |
|
455 |
{
|
|
456 |
grub_printf ("Cannot find /virtual-memory node.\n"); |
|
457 |
return; |
|
458 |
}
|
|
459 |
||
460 |
if (grub_ieee1275_get_property_length (node, "translations", &actual)) |
|
461 |
{
|
|
462 |
grub_printf ("Cannot find /virtual-memory/translations size.\n"); |
|
463 |
return; |
|
464 |
}
|
|
465 |
||
466 |
of_trans = grub_malloc (actual); |
|
467 |
if (!of_trans) |
|
468 |
{
|
|
469 |
grub_printf ("Cannot allocate translations buffer.\n"); |
|
470 |
return; |
|
471 |
}
|
|
472 |
||
473 |
if (grub_ieee1275_get_property (node, "translations", of_trans, actual, &actual)) |
|
474 |
{
|
|
475 |
grub_printf ("Cannot fetch /virtual-memory/translations property.\n"); |
|
476 |
return; |
|
477 |
}
|
|
478 |
||
479 |
of_num_trans = actual / sizeof(struct grub_ieee1275_translation); |
|
480 |
||
481 |
for (i = 0; i < of_num_trans; i++) |
|
482 |
{
|
|
483 |
struct grub_ieee1275_translation *p = &of_trans[i]; |
|
484 |
||
485 |
if (p->vaddr == 0x2000) |
|
486 |
{
|
|
487 |
grub_addr_t phys, tte = p->data; |
|
488 |
||
489 |
phys = tte & ~(0xff00000000001fffULL); |
|
490 |
||
491 |
grub_phys_start = phys; |
|
492 |
grub_phys_end = grub_phys_start + p->size; |
|
493 |
grub_dprintf ("loader", "Grub lives at phys_start[%lx] phys_end[%lx]\n", |
|
494 |
(unsigned long) grub_phys_start, |
|
495 |
(unsigned long) grub_phys_end); |
|
496 |
break; |
|
497 |
}
|
|
498 |
}
|
|
499 |
}
|
|
500 |
||
501 |
||
502 |
static grub_command_t cmd_linux, cmd_initrd; |
|
503 |
||
504 |
GRUB_MOD_INIT(linux) |
|
505 |
{
|
|
506 |
determine_phys_base (); |
|
507 |
fetch_translations (); |
|
508 |
||
509 |
cmd_linux = grub_register_command ("linux", grub_cmd_linux, |
|
510 |
0, N_("Load Linux.")); |
|
511 |
cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd, |
|
512 |
0, N_("Load initrd.")); |
|
513 |
my_mod = mod; |
|
514 |
}
|
|
515 |
||
516 |
GRUB_MOD_FINI(linux) |
|
517 |
{
|
|
518 |
grub_unregister_command (cmd_linux); |
|
519 |
grub_unregister_command (cmd_initrd); |
|
520 |
}
|