diff --git a/ChangeLog b/ChangeLog index 7473bcabe..94ddd806d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2004-10-28 Hollis Blanchard + + * boot/powerpc/ieee1275/cmain.c (cmain): Remove asm statements + which initialized BAT registers. + * boot/powerpc/ieee1275/ieee1275.c (IEEE1275_CALL_ENTRY_FN, + grub_ieee1275_common_hdr, INIT_IEEE1275_COMMON): + Move from here... + * include/grub/powerpc/ieee1275/ieee1275.h (IEEE1275_CALL_ENTRY_FN, + grub_ieee1275_common_hdr, INIT_IEEE1275_COMMON): + ... to here. + * kern/powerpc/ieee1275/openfw.c (grub_map): New function. + (grub_mapclaim): Likewise. + * loader/powerpc/ieee1275/linux.c (grub_load_linux): Use + grub_mapclaim instead of grub_ieee1275_claim. Assign linux_addr by + hand. + 2004-10-19 Hollis Blanchard * conf/powerpc-ieee1275.rmk (COMMON_ASFLAGS): Remove -fno-builtin. diff --git a/boot/powerpc/ieee1275/cmain.c b/boot/powerpc/ieee1275/cmain.c index 0f9366482..b3e5b648a 100644 --- a/boot/powerpc/ieee1275/cmain.c +++ b/boot/powerpc/ieee1275/cmain.c @@ -55,7 +55,6 @@ cmain (uint32_t r3, uint32_t r4 __attribute__((unused)), uint32_t r5) char **argv, args[256]; grub_ieee1275_phandle_t chosen; int argc = 0, actual; - long batl, batu; if (r5 == 0xdeadbeef) { @@ -81,27 +80,6 @@ cmain (uint32_t r3, uint32_t r4 __attribute__((unused)), uint32_t r5) grub_ieee1275_entry_fn = (intptr_t (*)(void *)) r5; } - /* Initialize BAT registers to unmapped to not generate overlapping - mappings below. */ - asm volatile ("mtibatu 0,%0" :: "r"(0)); - asm volatile ("mtibatu 1,%0" :: "r"(0)); - asm volatile ("mtibatu 2,%0" :: "r"(0)); - asm volatile ("mtibatu 3,%0" :: "r"(0)); - asm volatile ("mtdbatu 0,%0" :: "r"(0)); - asm volatile ("mtdbatu 1,%0" :: "r"(0)); - asm volatile ("mtdbatu 2,%0" :: "r"(0)); - asm volatile ("mtdbatu 3,%0" :: "r"(0)); - - /* Set up initial BAT table to only map the lowest 256 MB area. */ - batl = 0x00000000 | 0x10 | 0x02; - batu = 0x00000000 | 0x1ffc | 0x02; - - /* IBAT0 used for initial 256 MB segment */ - asm volatile ("mtibatl 3,%0; mtibatu 3,%1" :: "r" (batl), "r" (batu)); - /* DBAT0 used similar */ - asm volatile ("mtdbatl 3,%0; mtdbatu 3,%1" :: "r" (batl), "r" (batu)); - asm ("isync"); - /* If any argument was passed to the kernel (us), they are put in the bootargs property of /chosen. The string can be null (just the nul-character), so check that the size diff --git a/boot/powerpc/ieee1275/ieee1275.c b/boot/powerpc/ieee1275/ieee1275.c index dcf88cd18..bc0286479 100644 --- a/boot/powerpc/ieee1275/ieee1275.c +++ b/boot/powerpc/ieee1275/ieee1275.c @@ -26,25 +26,6 @@ intptr_t (*grub_ieee1275_entry_fn) (void *); -#ifndef IEEE1275_CALL_ENTRY_FN -#define IEEE1275_CALL_ENTRY_FN(args) (*grub_ieee1275_entry_fn) (args) -#endif - -/* All backcalls to the firmware is done by calling an entry function - which was passed to us from the bootloader. When doing the backcall, - a structure is passed which specifies what the firmware should do. - NAME is the requested service. NR_INS and NR_OUTS is the number of - passed arguments and the expected number of return values, resp. */ -struct grub_ieee1275_common_hdr -{ - char *name; - int nr_ins; - int nr_outs; -}; - -#define INIT_IEEE1275_COMMON(p, xname, xins, xouts) \ - (p)->name = xname; (p)->nr_ins = xins; (p)->nr_outs = xouts - /* FIXME is this function needed? */ grub_uint32_t grub_ieee1275_decode_int_4 (unsigned char *p) diff --git a/include/grub/powerpc/ieee1275/ieee1275.h b/include/grub/powerpc/ieee1275/ieee1275.h index 8102ee186..024b576c8 100644 --- a/include/grub/powerpc/ieee1275/ieee1275.h +++ b/include/grub/powerpc/ieee1275/ieee1275.h @@ -39,6 +39,27 @@ struct grub_ieee1275_mem_region unsigned int size; }; +extern intptr_t (*grub_ieee1275_entry_fn) (void *); + +#ifndef IEEE1275_CALL_ENTRY_FN +#define IEEE1275_CALL_ENTRY_FN(args) (*grub_ieee1275_entry_fn) (args) +#endif + +/* All backcalls to the firmware is done by calling an entry function + which was passed to us from the bootloader. When doing the backcall, + a structure is passed which specifies what the firmware should do. + NAME is the requested service. NR_INS and NR_OUTS is the number of + passed arguments and the expected number of return values, resp. */ +struct grub_ieee1275_common_hdr +{ + char *name; + int nr_ins; + int nr_outs; +}; + +#define INIT_IEEE1275_COMMON(p, xname, xins, xouts) \ + (p)->name = xname; (p)->nr_ins = xins; (p)->nr_outs = xouts + /* FIXME jrydberg: is this correct cell types? */ typedef intptr_t grub_ieee1275_ihandle_t; typedef intptr_t grub_ieee1275_phandle_t; @@ -103,6 +124,7 @@ grub_err_t EXPORT_FUNC(grub_devalias_iterate) (int (*hook) (struct grub_ieee1275_devalias *alias)); grub_err_t EXPORT_FUNC(grub_children_iterate) (char *devpath, int (*hook) (struct grub_ieee1275_devalias *alias)); +int EXPORT_FUNC(grub_claimmap) (grub_addr_t addr, grub_size_t size); void EXPORT_FUNC(abort) (void); diff --git a/kern/powerpc/ieee1275/openfw.c b/kern/powerpc/ieee1275/openfw.c index 43297835f..c60685230 100644 --- a/kern/powerpc/ieee1275/openfw.c +++ b/kern/powerpc/ieee1275/openfw.c @@ -137,3 +137,57 @@ grub_devalias_iterate (int (*hook) (struct grub_ieee1275_devalias *alias)) return 0; } + +/* Call the "map" method of /chosen/mmu. */ +int +grub_map (grub_addr_t phys, grub_addr_t virt, grub_uint32_t size, + grub_uint8_t mode) +{ + struct map_args { + struct grub_ieee1275_common_hdr common; + char *method; + grub_ieee1275_ihandle_t ihandle; + grub_uint32_t mode; + grub_uint32_t size; + grub_uint32_t virt; + grub_uint32_t phys; + int catch_result; + } args; + grub_ieee1275_ihandle_t mmu; + grub_ieee1275_ihandle_t chosen; + int len; + + grub_ieee1275_finddevice ("/chosen", &chosen); + if (chosen == 0) + return -1; + + grub_ieee1275_get_property (chosen, "mmu", &mmu, sizeof mmu, &len); + if (len != sizeof mmu) + return -1; + + INIT_IEEE1275_COMMON (&args.common, "call-method", 6, 1); + args.method = "map"; + args.ihandle = mmu; + args.phys = phys; + args.virt = virt; + args.size = size; + args.mode = mode; /* Format is WIMG0PP. */ + + if (IEEE1275_CALL_ENTRY_FN (&args) == -1) + return -1; + + return args.catch_result; +} + +int +grub_claimmap (grub_addr_t addr, grub_size_t size) +{ + if (grub_ieee1275_claim (addr, size, 0, 0)) + return -1; + if (grub_map (addr, addr, size, 0x00)) + { + grub_ieee1275_release (addr, size); + return -1; + } + return 0; +} diff --git a/loader/powerpc/ieee1275/linux.c b/loader/powerpc/ieee1275/linux.c index ac847d2ff..076da409b 100644 --- a/loader/powerpc/ieee1275/linux.c +++ b/loader/powerpc/ieee1275/linux.c @@ -188,12 +188,13 @@ grub_load_linux (int argc, char *argv[]) /* Reserve memory for the kernel. */ linux_size += 0x100000; - if (grub_ieee1275_claim (entry, linux_size, 0, &linux_addr) == -1) + if (grub_claimmap (entry, linux_size) == -1) { grub_error (GRUB_ERR_OUT_OF_MEMORY, "Can not claim memory"); goto fail; } - + linux_addr = entry; + /* Load every loadable segment in memory. */ for (i = 0; i < ehdr.e_phnum; i++) {