diff --git a/conf/mips-yeeloong.rmk b/conf/mips-yeeloong.rmk index 16909487d..a06b3fa5e 100644 --- a/conf/mips-yeeloong.rmk +++ b/conf/mips-yeeloong.rmk @@ -40,3 +40,10 @@ pkglib_MODULES += ata_pthru.mod ata_pthru_mod_SOURCES = disk/ata_pthru.c ata_pthru_mod_CFLAGS = $(COMMON_CFLAGS) ata_pthru_mod_LDFLAGS = $(COMMON_LDFLAGS) + +# For mmap.mod. +pkglib_MODULES += mmap.mod +mmap_mod_SOURCES = mmap/mmap.c mmap/mips/yeeloong/uppermem.c +mmap_mod_CFLAGS = $(COMMON_CFLAGS) +mmap_mod_LDFLAGS = $(COMMON_LDFLAGS) +mmap_mod_ASFLAGS = $(COMMON_ASFLAGS) diff --git a/include/grub/mips/yeeloong/memory.h b/include/grub/mips/yeeloong/memory.h index bc8f47b12..c85db712a 100644 --- a/include/grub/mips/yeeloong/memory.h +++ b/include/grub/mips/yeeloong/memory.h @@ -26,15 +26,22 @@ #endif #define GRUB_MACHINE_MEMORY_STACK_HIGH 0x801ffff0 -#define GRUB_MACHINE_MEMORY_USABLE 0x81000000 +#define GRUB_ARCH_LOWMEMVSTART 0x80000000 +#define GRUB_ARCH_LOWMEMPSTART 0x00000000 +#define GRUB_ARCH_LOWMEMMAXSIZE 0x10000000 +#define GRUB_ARCH_HIGHMEMPSTART 0x10000000 + #define GRUB_MACHINE_MEMORY_AVAILABLE 1 +#define GRUB_MACHINE_MEMORY_MAX_TYPE 1 + /* This one is special: it's used internally but is never reported + by firmware. */ +#define GRUB_MACHINE_MEMORY_HOLE 2 +#define GRUB_MACHINE_MEMORY_RESERVED GRUB_MACHINE_MEMORY_HOLE #ifndef ASM_FILE grub_err_t EXPORT_FUNC (grub_machine_mmap_iterate) (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)); -grub_err_t EXPORT_FUNC(grub_machine_mmap_iterate) - (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)); static inline grub_err_t grub_machine_mmap_register (grub_uint64_t start __attribute__ ((unused)), @@ -49,6 +56,15 @@ grub_machine_mmap_unregister (int handle __attribute__ ((unused))) { return GRUB_ERR_NONE; } + +grub_uint64_t grub_mmap_get_lower (void); +grub_uint64_t grub_mmap_get_upper (void); + +extern grub_uint32_t EXPORT_VAR (grub_arch_memsize); +extern grub_uint32_t EXPORT_VAR (grub_arch_highmemsize); +extern grub_uint32_t EXPORT_VAR (grub_arch_busclock); +extern grub_uint32_t EXPORT_VAR (grub_arch_cpuclock); + #endif #endif diff --git a/kern/mips/yeeloong/init.c b/kern/mips/yeeloong/init.c index 01acd4f1c..1bd9d2ed9 100644 --- a/kern/mips/yeeloong/init.c +++ b/kern/mips/yeeloong/init.c @@ -28,8 +28,6 @@ #include #include -#define RAMSIZE (64 << 20) - grub_uint32_t grub_get_rtc (void) { @@ -38,11 +36,48 @@ grub_get_rtc (void) return (calln++) >> 8; } +grub_err_t +grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, + grub_uint64_t, + grub_uint32_t)) +{ + hook (GRUB_ARCH_LOWMEMPSTART, grub_arch_memsize << 20, + GRUB_MACHINE_MEMORY_AVAILABLE); + hook (GRUB_ARCH_HIGHMEMPSTART, grub_arch_highmemsize << 20, + GRUB_MACHINE_MEMORY_AVAILABLE); + return GRUB_ERR_NONE; +} + + +static void * +get_modules_end (void) +{ + struct grub_module_info *modinfo; + struct grub_module_header *header; + grub_addr_t modbase; + + modbase = grub_arch_modules_addr (); + modinfo = (struct grub_module_info *) modbase; + + /* Check if there are any modules. */ + if ((modinfo == 0) || modinfo->magic != GRUB_MODULE_MAGIC) + return modinfo; + + for (header = (struct grub_module_header *) (modbase + modinfo->offset); + header < (struct grub_module_header *) (modbase + modinfo->size); + header = (struct grub_module_header *) ((char *) header + header->size)); + + return header; +} + void grub_machine_init (void) { - grub_mm_init_region ((void *) GRUB_MACHINE_MEMORY_USABLE, - RAMSIZE - (GRUB_MACHINE_MEMORY_USABLE & 0x7fffffff)); + void *modend; + modend = get_modules_end (); + grub_mm_init_region (modend, (grub_arch_memsize << 20) + - (((grub_addr_t) modend) - GRUB_ARCH_LOWMEMVSTART)); + /* FIXME: use upper memory as well. */ grub_install_get_time_ms (grub_rtc_get_time_ms); } @@ -69,11 +104,3 @@ grub_reboot (void) while (1); } -grub_err_t -grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, - grub_uint64_t, - grub_uint32_t)) -{ - hook (0, RAMSIZE, GRUB_MACHINE_MEMORY_AVAILABLE); - return GRUB_ERR_NONE; -} diff --git a/loader/mips/linux.c b/loader/mips/linux.c index 4d9045a65..635f84a28 100644 --- a/loader/mips/linux.c +++ b/loader/mips/linux.c @@ -26,6 +26,10 @@ #include #include #include +#include + +/* For frequencies. */ +#include #define ELF32_LOADMASK (0x00000000UL) #define ELF64_LOADMASK (0x0000000000000000ULL) @@ -176,7 +180,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), int size; void *extra = NULL; grub_uint32_t *linux_argv, *linux_envp; - char *linux_args; + char *linux_args, *linux_envs; grub_err_t err; if (argc == 0) @@ -218,7 +222,12 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), size += ALIGN_UP (sizeof ("rd_size=0xXXXXXXXXXXXXXXXX"), 4); /* For the environment. */ - size += sizeof (grub_uint32_t); + size += sizeof (grub_uint32_t); + size += 4 * sizeof (grub_uint32_t); + size += ALIGN_UP (sizeof ("memsize=XXXXXXXXXXXXXXXXXXXX"), 4) + + ALIGN_UP (sizeof ("highmemsize=XXXXXXXXXXXXXXXXXXXX"), 4) + + ALIGN_UP (sizeof ("busclock=XXXXXXXXXX"), 4) + + ALIGN_UP (sizeof ("cpuclock=XXXXXXXXXX"), 4); if (grub_elf_is_elf32 (elf)) err = grub_linux_load32 (elf, &extra, size); @@ -276,7 +285,27 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), linux_envp = extra; envp_off = (grub_uint8_t *) linux_envp - (grub_uint8_t *) playground; - linux_envp[0] = 0; + linux_envs = (char *) (linux_envp + 5); + grub_sprintf (linux_envs, "memsize=%lld", (unsigned long long) grub_mmap_get_lower () >> 20); + linux_envp[0] = (grub_uint8_t *) linux_envs - (grub_uint8_t *) playground + + target_addr; + linux_envs += ALIGN_UP (grub_strlen (linux_envs) + 1, 4); + grub_sprintf (linux_envs, "highmemsize=%lld", (unsigned long long) grub_mmap_get_upper () >> 20); + linux_envp[1] = (grub_uint8_t *) linux_envs - (grub_uint8_t *) playground + + target_addr; + linux_envs += ALIGN_UP (grub_strlen (linux_envs) + 1, 4); + + grub_sprintf (linux_envs, "busclock=%d", grub_arch_busclock); + linux_envp[2] = (grub_uint8_t *) linux_envs - (grub_uint8_t *) playground + + target_addr; + linux_envs += ALIGN_UP (grub_strlen (linux_envs) + 1, 4); + grub_sprintf (linux_envs, "cpuclock=%d", grub_arch_cpuclock); + linux_envp[3] = (grub_uint8_t *) linux_envs - (grub_uint8_t *) playground + + target_addr; + linux_envs += ALIGN_UP (grub_strlen (linux_envs) + 1, 4); + + + linux_envp[4] = 0; grub_loader_set (grub_linux_boot, grub_linux_unload, 1); initrd_loaded = 0; diff --git a/mmap/mips/yeeloong/uppermem.c b/mmap/mips/yeeloong/uppermem.c new file mode 100644 index 000000000..3c5f814de --- /dev/null +++ b/mmap/mips/yeeloong/uppermem.c @@ -0,0 +1,66 @@ +/* Compute amount of lower and upper memory till the first hole. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include + +grub_uint64_t +grub_mmap_get_lower (void) +{ + grub_uint64_t lower = 0; + + auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); + int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, + grub_uint32_t type) + { + if (type != GRUB_MACHINE_MEMORY_AVAILABLE) + return 0; + if (addr == 0) + lower = size; + return 0; + } + + grub_mmap_iterate (hook); + if (lower > GRUB_ARCH_LOWMEMMAXSIZE) + lower = GRUB_ARCH_LOWMEMMAXSIZE; + return lower; +} + +grub_uint64_t +grub_mmap_get_upper (void) +{ + grub_uint64_t upper = 0; + + auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); + int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, + grub_uint32_t type) + { + if (type != GRUB_MACHINE_MEMORY_AVAILABLE) + return 0; + if (addr <= GRUB_ARCH_HIGHMEMPSTART && addr + size + > GRUB_ARCH_HIGHMEMPSTART) + upper = addr + size - GRUB_ARCH_HIGHMEMPSTART; + return 0; + } + + grub_mmap_iterate (hook); + return upper; +} diff --git a/mmap/mmap.c b/mmap/mmap.c index 7598cf501..d379a99f9 100644 --- a/mmap/mmap.c +++ b/mmap/mmap.c @@ -52,7 +52,7 @@ grub_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, #ifdef GRUB_MACHINE_MEMORY_AVAILABLE [GRUB_MACHINE_MEMORY_AVAILABLE] = 1, #endif -#ifdef GRUB_MACHINE_MEMORY_RESERVED +#if defined (GRUB_MACHINE_MEMORY_RESERVED) && GRUB_MACHINE_MEMORY_RESERVED != GRUB_MACHINE_MEMORY_HOLE [GRUB_MACHINE_MEMORY_RESERVED] = 3, #endif #ifdef GRUB_MACHINE_MEMORY_ACPI