=== modified file 'Makefile.util.def' --- Makefile.util.def 2012-09-26 12:51:13 +0000 +++ Makefile.util.def 2012-10-22 18:29:17 +0000 @@ -469,6 +469,7 @@ enable = mips_loongson; enable = ia64_efi; enable = powerpc_ieee1275; + enable = arm_uboot; }; script = { === modified file 'conf/Makefile.common' --- conf/Makefile.common 2012-04-18 21:37:25 +0000 +++ conf/Makefile.common 2012-10-22 18:29:17 +0000 @@ -37,6 +37,12 @@ CFLAGS_PLATFORM += -mno-app-regs LDFLAGS_PLATFORM = -Wl,-melf64_sparc -mno-relax endif +if COND_arm +# Image entry point always in ARM (A32) state - ensure proper functionality if +# the rest is built for the Thumb (T32) state. + CFLAGS_PLATFORM += -mthumb-interwork -mno-unaligned-access + CCASFLAGS_PLATFORM = -Wa,-mimplicit-it=thumb +endif # Other options @@ -58,6 +64,7 @@ if ! COND_i386_multiboot if ! COND_i386_ieee1275 if ! COND_x86_64_efi +if ! COND_arm LDADD_KERNEL += -lgcc endif endif @@ -66,9 +73,14 @@ endif endif endif +endif CFLAGS_KERNEL = $(CFLAGS_CPU) $(CFLAGS_PLATFORM) -ffreestanding +if ! COND_arm LDFLAGS_KERNEL = $(LDFLAGS_CPU) $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) -static-libgcc +else +LDFLAGS_KERNEL = $(LDFLAGS_CPU) $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) +endif CPPFLAGS_KERNEL = $(CPPFLAGS_CPU) $(CPPFLAGS_PLATFORM) CCASFLAGS_KERNEL = $(CCASFLAGS_CPU) $(CCASFLAGS_PLATFORM) if COND_CYGWIN @@ -108,6 +120,8 @@ CFLAGS_GNULIB = -Wno-undef -Wno-sign-compare -Wno-unused -Wno-unused-parameter -Wno-redundant-decls -Wno-unreachable-code -Wno-conversion -Wno-old-style-definition -Wno-unsafe-loop-optimizations CPPFLAGS_GNULIB = -I$(top_builddir)/grub-core/gnulib -I$(top_srcdir)/grub-core/gnulib +CPPFLAGS_LIBFDT = -I$(top_srcdir)/grub-core/lib/libfdt + CFLAGS_POSIX = -fno-builtin CPPFLAGS_POSIX = -I$(top_srcdir)/grub-core/lib/posix_wrap === modified file 'configure.ac' --- configure.ac 2012-09-05 14:09:41 +0000 +++ configure.ac 2012-10-22 18:29:17 +0000 @@ -79,6 +79,9 @@ target_cpu=mips; machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_CPU_MIPS=1"; ;; + arm*) + target_cpu=arm; + ;; esac # Specify the platform (such as firmware). @@ -99,6 +102,7 @@ mipsel-*) platform=loongson ;; mips-*) platform=arc ;; ia64-*) platform=efi ;; + arm-*) platform=uboot ;; *) AC_MSG_ERROR([unsupported CPU: "$target_cpu"]) ;; esac else @@ -133,6 +137,7 @@ mipsel-yeeloong) platform=loongson ;; mipsel-fuloong) platform=loongson ;; mipsel-loongson) ;; + arm-uboot) platform=uboot ;; *-emu) ;; *) AC_MSG_ERROR([platform "$platform" is not supported for target CPU "$target_cpu"]) ;; esac @@ -164,6 +169,7 @@ multiboot) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_MULTIBOOT=1" ;; efi) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_EFI=1" ;; ieee1275) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_IEEE1275=1" ;; + uboot) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_UBOOT=1" ;; qemu) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_QEMU=1" ;; pc) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_PCBIOS=1" ;; emu) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_EMU=1" ;; @@ -172,6 +178,7 @@ arc) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_ARC=1" ;; esac case "$target_cpu" in + arm) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_ARM=1" ;; mips |mipsel) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_MIPS=1" ;; sparc64) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_SPARC64=1" ;; esac @@ -669,7 +676,8 @@ CFLAGS="$TARGET_CFLAGS -nostdlib -Wl,--defsym,___main=0x8100 -Wno-error" fi CPPFLAGS="$TARGET_CPPFLAGS" -if test x$target_cpu = xi386 || test x$target_cpu = xx86_64 ; then + +if test x$target_cpu = xi386 || test x$target_cpu = xx86_64 || test x$target_cpu = xarm ; then LIBS= else LIBS=-lgcc @@ -1116,6 +1124,8 @@ AM_CONDITIONAL([COND_mips], [test x$target_cpu = xmips -o x$target_cpu = xmipsel]) AM_CONDITIONAL([COND_mipsel], [test x$target_cpu = xmipsel]) AM_CONDITIONAL([COND_mipseb], [test x$target_cpu = xmips]) +AM_CONDITIONAL([COND_arm], [test x$target_cpu = xarm ]) +AM_CONDITIONAL([COND_arm_uboot], [test x$target_cpu = xarm -a x$platform = xuboot]) AM_CONDITIONAL([COND_HOST_HURD], [test x$host_kernel = xhurd]) AM_CONDITIONAL([COND_HOST_LINUX], [test x$host_kernel = xlinux]) @@ -1146,6 +1156,9 @@ if test x${cpudir} = xmipsel; then cpudir=mips; fi +if test x${cpudir} = xarmel; then + cpudir=arm; +fi grub_CHECK_LINK_DIR if test x"$link_dir" = xyes ; then AC_CONFIG_LINKS([include/grub/cpu:include/grub/$cpudir]) === modified file 'gentpl.py' --- gentpl.py 2012-09-12 06:27:26 +0000 +++ gentpl.py 2012-10-22 18:29:17 +0000 @@ -23,7 +23,7 @@ "i386_multiboot", "i386_ieee1275", "x86_64_efi", "mips_loongson", "sparc64_ieee1275", "powerpc_ieee1275", "mips_arc", "ia64_efi", - "mips_qemu_mips" ] + "mips_qemu_mips", "arm_uboot" ] GROUPS = {} @@ -36,10 +36,12 @@ GROUPS["mips"] = [ "mips_loongson", "mips_qemu_mips", "mips_arc" ] GROUPS["sparc64"] = [ "sparc64_ieee1275" ] GROUPS["powerpc"] = [ "powerpc_ieee1275" ] +GROUPS["arm"] = [ "arm_uboot" ] # Groups based on firmware GROUPS["efi"] = [ "i386_efi", "x86_64_efi", "ia64_efi" ] GROUPS["ieee1275"] = [ "i386_ieee1275", "sparc64_ieee1275", "powerpc_ieee1275" ] +GROUPS["uboot"] = [ "arm_uboot" ] # emu is a special case so many core functionality isn't needed on this platform GROUPS["noemu"] = GRUB_PLATFORMS[:]; GROUPS["noemu"].remove("emu") @@ -57,10 +59,13 @@ for i in GROUPS["videoinkernel"]: GROUPS["videomodules"].remove(i) # Similar for terminfo -GROUPS["terminfoinkernel"] = ["mips_loongson", "mips_arc", "mips_qemu_mips" ] + GROUPS["ieee1275"]; +GROUPS["terminfoinkernel"] = ["mips_loongson", "mips_arc", "mips_qemu_mips" ] + GROUPS["ieee1275"] + GROUPS["uboot"]; GROUPS["terminfomodule"] = GRUB_PLATFORMS[:]; for i in GROUPS["terminfoinkernel"]: GROUPS["terminfomodule"].remove(i) +# Flattened Device Trees (FDT) +GROUPS["fdt"] = [ "arm_uboot" ] + # Miscelaneous groups schedulded to disappear in future GROUPS["i386_coreboot_multiboot_qemu"] = ["i386_coreboot", "i386_multiboot", "i386_qemu"] GROUPS["nopc"] = GRUB_PLATFORMS[:]; GROUPS["nopc"].remove("i386_pc") === modified file 'grub-core/Makefile.am' --- grub-core/Makefile.am 2012-10-12 13:04:02 +0000 +++ grub-core/Makefile.am 2012-10-22 18:29:17 +0000 @@ -143,6 +143,11 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h endif +if COND_arm_uboot +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/uboot/uboot.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/uboot/disk.h +endif + if COND_mips KERNEL_HEADER_FILES += $(top_builddir)/include/grub/cpu/kernel.h endif === modified file 'grub-core/Makefile.core.def' --- grub-core/Makefile.core.def 2012-09-08 07:40:24 +0000 +++ grub-core/Makefile.core.def 2012-10-22 18:29:17 +0000 @@ -67,6 +67,9 @@ emu_cflags = '$(CFLAGS_GNULIB)'; emu_cppflags = '$(CPPFLAGS_GNULIB)'; + arm_uboot_ldflags = '-Wl,-Ttext=0x08000000'; + arm_uboot_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version'; + i386_pc_startup = kern/i386/pc/startup.S; i386_efi_startup = kern/i386/efi/startup.S; x86_64_efi_startup = kern/x86_64/efi/startup.S; @@ -77,6 +80,7 @@ mips_startup = kern/mips/startup.S; sparc64_ieee1275_startup = kern/sparc64/ieee1275/crt0.S; powerpc_ieee1275_startup = kern/powerpc/ieee1275/startup.S; + arm_uboot_startup = kern/arm/uboot/startup.S; common = kern/command.c; common = kern/corecmd.c; @@ -199,6 +203,17 @@ sparc64_ieee1275 = kern/sparc64/dl.c; sparc64_ieee1275 = kern/sparc64/ieee1275/ieee1275.c; + uboot = disk/uboot/ubootdisk.c; + uboot = kern/uboot/uboot.c; + uboot = kern/uboot/glue.c; + uboot = kern/uboot/crc32.c; + uboot = kern/uboot/init.c; + uboot = kern/uboot/hw.c; + uboot = term/uboot/console.c; + + arm = kern/arm/dl.c; + arm = lib/arm/libgcc.S; + emu = disk/host.c; emu = gnulib/progname.c; emu = gnulib/error.c; @@ -595,6 +610,8 @@ module = { name = cat; common = commands/cat.c; + arm = lib/arg.c; + arm = commands/extcmd.c; }; module = { @@ -665,6 +682,7 @@ efi = lib/efi/halt.c; ieee1275 = lib/ieee1275/halt.c; emu = lib/emu/halt.c; + uboot = lib/uboot/halt.c; }; module = { @@ -678,6 +696,7 @@ mips_arc = lib/mips/arc/reboot.c; mips_loongson = lib/mips/loongson/reboot.c; mips_qemu_mips = lib/mips/qemu_mips/reboot.c; + uboot = lib/uboot/reboot.c; common = commands/reboot.c; }; @@ -1300,6 +1319,7 @@ name = datetime; cmos = lib/cmos_datetime.c; efi = lib/efi/datetime.c; + uboot = lib/uboot/datetime.c; sparc64_ieee1275 = lib/ieee1275/datetime.c; powerpc_ieee1275 = lib/ieee1275/datetime.c; sparc64_ieee1275 = lib/ieee1275/cmos.c; @@ -1319,6 +1339,7 @@ extra_dist = lib/powerpc/setjmp.S; extra_dist = lib/ia64/setjmp.S; extra_dist = lib/ia64/longjmp.S; + extra_dist = lib/arm/setjmp.S; }; module = { @@ -1389,6 +1410,19 @@ enable = x86; }; +library = { + name = libfdtlib.a; + common = lib/libfdt/fdt.c; + common = lib/libfdt/fdt_ro.c; + common = lib/libfdt/fdt_rw.c; + common = lib/libfdt/fdt_strerror.c; + common = lib/libfdt/fdt_sw.c; + common = lib/libfdt/fdt_wip.c; + cppflags = '$(CPPFLAGS_LIBFDT)'; + + enable = arm; +}; + module = { name = linux; x86 = loader/i386/linux.c; @@ -1397,8 +1431,12 @@ powerpc_ieee1275 = loader/powerpc/ieee1275/linux.c; sparc64_ieee1275 = loader/sparc64/ieee1275/linux.c; ia64_efi = loader/ia64/efi/linux.c; + arm_uboot = loader/arm/uboot/linux.c; common = lib/cmdline.c; enable = noemu; + + fdt_cppflags = '$(CPPFLAGS_LIBFDT)'; + fdt_ldadd = libfdtlib.a; }; module = { === added directory 'grub-core/disk/uboot' === added file 'grub-core/disk/uboot/ubootdisk.c' --- grub-core/disk/uboot/ubootdisk.c 1970-01-01 00:00:00 +0000 +++ grub-core/disk/uboot/ubootdisk.c 2012-10-22 18:29:17 +0000 @@ -0,0 +1,345 @@ +/* ubootdisk.c - disk subsystem support for U-Boot platforms */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2012 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 +#include +#include +#include +#include +#include + +static struct ubootdisk_data *fd_devices; +static struct ubootdisk_data *hd_devices; +static struct ubootdisk_data *cd_devices; + +/* + * grub_ubootdisk_register(): + * Called for each disk device enumerated as part of U-Boot initialization + * code. + */ +grub_err_t +grub_ubootdisk_register (struct device_info *newdev, int handle) +{ + struct ubootdisk_data *d; + enum disktype type; + +#define STOR_TYPE(x) ((x) & 0x0ff0) + switch (STOR_TYPE (newdev->type)) + { + case DT_STOR_IDE: + case DT_STOR_SATA: + /* hd */ + type = hd; + break; + case DT_STOR_MMC: + case DT_STOR_USB: + /* fd */ + type = fd; + break; + default: + return GRUB_ERR_BAD_DEVICE; + break; + } + + d = (struct ubootdisk_data *) grub_malloc (sizeof (struct ubootdisk_data)); + if (!d) + return GRUB_ERR_OUT_OF_MEMORY; + d->handle = handle; + d->cookie = newdev->cookie; + d->opencount = 0; + + switch (type) + { + case cd: + grub_dprintf ("ubootdisk", "registering cd device\n"); + d->next = cd_devices; + cd_devices = d; + + break; + case fd: + grub_dprintf ("ubootdisk", "registering fd device\n"); + d->next = fd_devices; + fd_devices = d; + + break; + case hd: + grub_dprintf ("ubootdisk", "registering hd device\n"); + d->next = hd_devices; + hd_devices = d; + + break; + default: + grub_free (d); + return GRUB_ERR_BAD_DEVICE; + } + + return 0; +} + +/* + * uboot_disk_iterate(): + * Itarator over enumerated disk devices. + */ +static int +uboot_disk_iterate (int (*hook) (const char *name), grub_disk_pull_t pull) +{ + struct ubootdisk_data *d; + char buf[16]; + int count; + + switch (pull) + { + case GRUB_DISK_PULL_NONE: + /* "hd" - built-in mass-storage */ + for (d = hd_devices, count = 0; d; d = d->next, count++) + { + grub_snprintf (buf, sizeof (buf) - 1, "hd%d", count); + grub_dprintf ("ubootdisk", "iterating %s\n", buf); + if (hook (buf)) + return 1; + } + break; + case GRUB_DISK_PULL_REMOVABLE: + /* "floppy" - removable mass storage */ + for (d = fd_devices, count = 0; d; d = d->next, count++) + { + grub_snprintf (buf, sizeof (buf) - 1, "fd%d", count); + grub_dprintf ("ubootdisk", "iterating %s\n", buf); + if (hook (buf)) + return 1; + } + + /* "cdrom" - removeable read-only storage */ + for (d = cd_devices, count = 0; d; d = d->next, count++) + { + grub_snprintf (buf, sizeof (buf) - 1, "cd%d", count); + grub_dprintf ("ubootdisk", "iterating %s\n", buf); + if (hook (buf)) + return 1; + } + break; + default: + return 0; + } + + return 0; +} + +/* Helper function for uboot_disk_open. */ +static struct ubootdisk_data * +get_device (struct ubootdisk_data *devices, int num) +{ + struct ubootdisk_data *d; + + for (d = devices; d && num; d = d->next, num--) + ; + + if (num == 0) + return d; + + return NULL; +} + +/* + * uboot_disk_open(): + * Opens a disk device already enumerated. + */ +static grub_err_t +uboot_disk_open (const char *name, struct grub_disk *disk) +{ + struct ubootdisk_data *d; + struct device_info *devinfo; + int num; + int retval; + + grub_dprintf ("ubootdisk", "Opening '%s'\n", name); + + num = grub_strtoul (name + 2, 0, 10); + if (grub_errno != GRUB_ERR_NONE) + { + grub_dprintf ("ubootdisk", "Opening '%s' failed, invalid number\n", + name); + goto fail; + } + + if (name[1] != 'd') + { + grub_dprintf ("ubootdisk", "Opening '%s' failed, invalid name\n", name); + goto fail; + } + + switch (name[0]) + { + case 'f': + d = get_device (fd_devices, num); + break; + case 'c': + d = get_device (cd_devices, num); + break; + case 'h': + d = get_device (hd_devices, num); + break; + default: + goto fail; + } + + if (!d) + goto fail; + + /* + * Subsystems may call open on the same device recursively - but U-Boot + * does not deal with this. So simply keep track of number of calls and + * return success if already open. + */ + if (d->opencount > 0) + { + grub_dprintf ("ubootdisk", "(%s) already open\n", disk->name); + d->opencount++; + retval = 0; + } + else + { + retval = ub_dev_open (d->handle); + if (retval != 0) + goto fail; + d->opencount = 1; + } + + grub_dprintf ("ubootdisk", "cookie: 0x%08x\n", (grub_addr_t) d->cookie); + disk->id = (grub_addr_t) d->cookie; + + /* Device has previously been enumerated, so this should never fail */ + if ((devinfo = ub_dev_get (d->handle)) == NULL) + goto fail; + + d->block_size = devinfo->di_stor.block_size; + if (d->block_size == 0) + { + grub_printf ("%s: no block size!\n", __FUNCTION__); + return GRUB_ERR_IO; + } + + for (disk->log_sector_size = 0; + (1U << disk->log_sector_size) < d->block_size; + disk->log_sector_size++); + + grub_dprintf ("ubootdisk", "(%s) blocksize=%d, log_sector_size=%d\n", + disk->name, d->block_size, disk->log_sector_size); + + disk->total_sectors = GRUB_DISK_SIZE_UNKNOWN; + disk->data = d; + + return GRUB_ERR_NONE; + +fail: + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such device"); +} + +static void +uboot_disk_close (struct grub_disk *disk) +{ + struct ubootdisk_data *d; + int retval; + + d = disk->data; + + /* + * In mirror of open function, keep track of number of calls to close and + * send on to U-Boot only when opencount would decrease to 0. + */ + if (d->opencount > 1) + { + grub_dprintf ("ubootdisk", "Closed (%s)\n", disk->name); + + d->opencount--; + } + else if (d->opencount == 1) + { + retval = ub_dev_close (d->handle); + d->opencount--; + grub_dprintf ("ubootdisk", "closed %s (%d)\n", disk->name, retval); + } + else + { + grub_dprintf ("ubootdisk", "device %s not open!\n", disk->name); + } +} + +/* + * uboot_disk_read(): + * Called from within disk subsystem to read a sequence of blocks into the + * disk cache. Maps directly on top of U-Boot API, only wrap in some error + * handling. + */ +static grub_err_t +uboot_disk_read (struct grub_disk *disk, + grub_disk_addr_t offset, grub_size_t numblocks, char *buf) +{ + struct ubootdisk_data *d; + lbasize_t real_size; + int retval; + + d = disk->data; + + retval = ub_dev_read (d->handle, buf, numblocks, offset, &real_size); + grub_dprintf ("ubootdisk", + "retval=%d, numblocks=%d, real_size=%llu, sector=%llu\n", + retval, numblocks, (grub_uint64_t) real_size, + (grub_uint64_t) offset); + if (retval != 0) + return grub_error (GRUB_ERR_IO, "U-Boot disk read error"); + + return GRUB_ERR_NONE; +} + +static grub_err_t +uboot_disk_write (struct grub_disk *disk __attribute__ ((unused)), + grub_disk_addr_t sector __attribute__ ((unused)), + grub_size_t size __attribute__ ((unused)), + const char *buf __attribute__ ((unused))) +{ + grub_dprintf ("ubootdisk", "attempt to write\n"); + return GRUB_ERR_NOT_IMPLEMENTED_YET; +} + +static struct grub_disk_dev grub_ubootdisk_dev = { + .name = "ubootdisk", + .id = GRUB_DISK_DEVICE_UBOOTDISK_ID, + .iterate = uboot_disk_iterate, + .open = uboot_disk_open, + .close = uboot_disk_close, + .read = uboot_disk_read, + .write = uboot_disk_write, + .next = 0 +}; + +void +grub_ubootdisk_init (void) +{ + grub_disk_dev_register (&grub_ubootdisk_dev); +} + +void +grub_ubootdisk_fini (void) +{ + grub_disk_dev_unregister (&grub_ubootdisk_dev); +} === added directory 'grub-core/kern/arm' === added file 'grub-core/kern/arm/dl.c' --- grub-core/kern/arm/dl.c 1970-01-01 00:00:00 +0000 +++ grub-core/kern/arm/dl.c 2012-10-22 18:29:17 +0000 @@ -0,0 +1,327 @@ +/* dl.c - arch-dependent part of loadable module support */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2012 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 +#include +#include + +#if !defined(__thumb2__) +#error "Relocations not implemented for A32 ("ARM") instruction set yet!" +#endif + +#ifdef DL_DEBUG +static const char *symstrtab; + +/* + * This is a bit of a hack, setting the symstrtab pointer to the last STRTAB + * section in the module (which is where symbol names are in the objects I've + * inspected manually). + */ +static void +set_symstrtab (Elf_Ehdr * e) +{ + int i; + Elf_Shdr *s; + + symstrtab = NULL; + + for (i = 0, s = (Elf_Shdr *) ((grub_uint32_t) e + e->e_shoff); + i < e->e_shnum; + i++, s = (Elf_Shdr *) ((grub_uint32_t) s + e->e_shentsize)) + if (s->sh_type == SHT_STRTAB) + symstrtab = (void *) ((grub_addr_t) e + s->sh_offset); +} + +static const char * +get_symbolname (Elf_Sym * sym) +{ + const char *symbolname = symstrtab + sym->st_name; + + return (*symbolname ? symbolname : NULL); +} +#endif /* DL_DEBUG */ + + +/* + * Simple relocation of 32-bit value (in literal pool) + */ +static grub_err_t +reloc_abs32 (Elf_Word * addr, Elf_Sym * sym) +{ +#ifdef DL_DEBUG + grub_printf ("%s: ABS32 @ 0x%08x -> %s @ 0x%08x\n", + __FUNCTION__, (grub_addr_t) addr, + get_symbolname (sym), sym->st_value); +#endif + + *addr += sym->st_value; + + return GRUB_ERR_NONE; +} + +/* + * R_ARM_THM_CALL/THM_JUMP24 + * + * Deals with relocation of Thumb (T32) instruction set relative branches + * B.W, BL and BLX + * + * 32-bit Thumb instructions can be 16-bit aligned, and are fetched + * little-endian, requiring some additional fiddling. + */ +static grub_err_t +reloc_thm_call (grub_uint16_t * addr, Elf_Sym * sym) +{ + grub_int32_t offset, offset_low, offset_high; + grub_uint32_t sign, j1, j2, is_blx; + grub_uint32_t insword, insmask; + + /* Extract instruction word in alignment-safe manner */ + insword = (*addr << 16) | *(addr + 1); + insmask = 0xf800d000; + + /* B.W/BL or BLX? Affects range and expected target state */ + if (((insword >> 12) & 0xd) == 0xc) + is_blx = 1; + else + is_blx = 0; + + offset_low = -16777216; + offset_high = is_blx ? 16777212 : 16777214; + +#ifdef DL_DEBUG + grub_printf ("%s: %s @ 0x%08x -> %s @ 0x%08x\n", + __FUNCTION__, is_blx ? "BLX" : "B(L)", + (grub_addr_t) addr, get_symbolname (sym), sym->st_value); +#endif + + /* Extract bitfields from instruction words */ + sign = (insword >> 26) & 1; + j1 = (insword >> 13) & 1; + j2 = (insword >> 11) & 1; + offset = (sign << 24) | ((~(j1 ^ sign) & 1) << 23) | + ((~(j2 ^ sign) & 1) << 22) | + ((insword & 0x03ff0000) >> 4) | ((insword & 0x000007ff) << 1); + + /* Sign adjust and calculate offset */ + if (offset & 0x01000000) + offset -= 0x02000000; + offset += sym->st_value - (grub_uint32_t) addr; + + if ((offset < offset_low) || (offset > offset_high)) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + N_("offset %d (0x%08x) is out of range"), + offset, offset); + + /* If BLX, target symbol must be ARM (target address LSB == 0) */ + if (is_blx && (offset & 1)) + return grub_error + (GRUB_ERR_BUG, N_("Relocation targeting wrong execution state")); + + /* Reassemble instruction word */ + sign = (offset >> 24) & 1; + j1 = sign ^ (~(offset >> 23) & 1); + j2 = sign ^ (~(offset >> 22) & 1); + insword = (insword & insmask) | + (sign << 26) | + (((offset >> 12) & 0x03ff) << 16) | + (j1 << 13) | (j2 << 11) | ((offset >> 1) & 0x07ff); + + /* Write instruction word back in alignment-safe manner */ + *(grub_uint16_t *) addr = (insword >> 16) & 0xffff; + *(grub_uint16_t *) (addr + 1) = insword & 0xffff; + + return GRUB_ERR_NONE; +} + +/* + * find_segment(): finds a module segment matching sh_info + */ +static grub_dl_segment_t +find_segment (grub_dl_segment_t seg, Elf32_Word sh_info) +{ + for (; seg; seg = seg->next) + if (seg->section == sh_info) + return seg; + + return NULL; +} + +/* + * do_relocations(): + * Iterate over all relocations in section, calling appropriate functions + * for patching. + */ +static grub_err_t +do_relocations (Elf_Shdr * relhdr, Elf_Ehdr * e, grub_dl_t mod) +{ + grub_dl_segment_t seg; + Elf_Rel *rel; + Elf_Sym *sym; + int i, entnum; + + entnum = relhdr->sh_size / sizeof (Elf_Rel); + + /* Find the target segment for this relocation section. */ + seg = find_segment (mod->segment, relhdr->sh_info); + if (!seg) + return grub_error (GRUB_ERR_EOF, N_("relocation segment not found")); + + rel = (Elf_Rel *) ((grub_addr_t) e + relhdr->sh_offset); + + /* Step through all relocations */ + for (i = 0, sym = mod->symtab; i < entnum; i++) + { + Elf_Word *addr; + int relsym, reltype; + grub_err_t retval; + + if (seg->size < rel[i].r_offset) + return grub_error (GRUB_ERR_BAD_MODULE, + "reloc offset is out of the segment"); + relsym = ELF_R_SYM (rel[i].r_info); + reltype = ELF_R_TYPE (rel[i].r_info); + addr = (Elf_Word *) ((grub_addr_t) seg->addr + rel[i].r_offset); + + switch (reltype) + { + case R_ARM_ABS32: + { + /* Data will be naturally aligned */ + retval = reloc_abs32 (addr, &sym[relsym]); + if (retval != GRUB_ERR_NONE) + return retval; + } + break; + case R_ARM_THM_CALL: + case R_ARM_THM_JUMP24: + { + /* Thumb instructions can be 16-bit aligned */ + retval = reloc_thm_call ((grub_uint16_t *) addr, &sym[relsym]); + if (retval != GRUB_ERR_NONE) + return retval; + } + break; + default: + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + N_("relocation 0x%x is not implemented yet"), + reltype); + } + } + + return GRUB_ERR_NONE; +} + + +/* + * Check if EHDR is a valid ELF header. + */ +grub_err_t +grub_arch_dl_check_header (void *ehdr) +{ + Elf_Ehdr *e = ehdr; + + /* Check the magic numbers. */ + if (e->e_ident[EI_CLASS] != ELFCLASS32 + || e->e_ident[EI_DATA] != ELFDATA2LSB || e->e_machine != EM_ARM) + return grub_error (GRUB_ERR_BAD_OS, + N_("invalid arch-dependent ELF magic")); + + return GRUB_ERR_NONE; +} + +/* + * Verify that provided ELF header contains reference to a symbol table + */ +static int +has_symtab (Elf_Ehdr * e) +{ + int i; + Elf_Shdr *s; + + for (i = 0, s = (Elf_Shdr *) ((grub_uint32_t) e + e->e_shoff); + i < e->e_shnum; + i++, s = (Elf_Shdr *) ((grub_uint32_t) s + e->e_shentsize)) + if (s->sh_type == SHT_SYMTAB) + return 1; + + return 0; +} + +/* + * grub_arch_dl_relocate_symbols(): + * Only externally visible function in this file. + * Locates the relocations section of the ELF object, and calls + * do_relocations() to deal with it. + */ +grub_err_t +grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) +{ + Elf_Ehdr *e = ehdr; + Elf_Shdr *s; + unsigned i; + + if (!has_symtab (e)) + return grub_error (GRUB_ERR_BAD_MODULE, N_("no symbol table")); + +#ifdef DL_DEBUG + set_symstrtab (e); +#endif + +#define FIRST_SHDR(x) ((Elf_Shdr *) ((grub_addr_t)(x) + (x)->e_shoff)) +#define NEXT_SHDR(x, y) ((Elf_Shdr *) ((grub_addr_t)(y) + (x)->e_shentsize)) + + for (i = 0, s = FIRST_SHDR (e); i < e->e_shnum; i++, s = NEXT_SHDR (e, s)) + { + grub_err_t ret; + + switch (s->sh_type) + { + case SHT_REL: + { + /* Relocations, no addends */ + ret = do_relocations (s, e, mod); + if (ret != GRUB_ERR_NONE) + return ret; + } + break; + case SHT_NULL: + case SHT_PROGBITS: + case SHT_SYMTAB: + case SHT_STRTAB: + case SHT_NOBITS: + case SHT_ARM_ATTRIBUTES: + break; + case SHT_RELA: + default: + { + grub_printf ("unhandled section_type: %d (0x%08x)\n", + s->sh_type, s->sh_type); + return GRUB_ERR_NOT_IMPLEMENTED_YET; + }; + } + } + +#undef FIRST_SHDR +#undef NEXT_SHDR + + return GRUB_ERR_NONE; +} === added directory 'grub-core/kern/arm/uboot' === added file 'grub-core/kern/arm/uboot/startup.S' --- grub-core/kern/arm/uboot/startup.S 1970-01-01 00:00:00 +0000 +++ grub-core/kern/arm/uboot/startup.S 2012-10-22 18:29:17 +0000 @@ -0,0 +1,173 @@ +/* + * (C) Copyright 2012 ARM ltd. + * + * Based on U-boot example written by Rafal Jaworowski + * + * This program 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 2 of + * the License, or (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#include +#include +#include + +/* + * GRUB is called from U-Boot as a Linux Kernel type image, which + * means among other things that it always enters in ARM state. + * + * + * Overview of GRUB image layout: + * + * _start: + * Entry point (1 ARM branch instruction, to "codestart") + * grub_total_module_size: + * Data field: Size of included module blob + * (when generated by grub-mkimage) + * codestart: + * Remainder of statically-linked executable code and data. + * __bss_start: + * Start of included module blob. + * Also where global/static variables are located. + * _end: + * End of bss region (but not necessarily module blob). + * : + * Any part of the module blob that extends beyond _end. + * : + * Loadable modules, post relocation. + * : + * : + */ + + .text + .arm +FUNCTION(_start) +.extern __bss_start +.extern _end +.extern uboot_machine_type +.extern uboot_boot_data + b codestart + + @ Size of final image integrated module blob - set by grub-mkimage + . = _start + GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE +VARIABLE(grub_total_module_size) + .long 0 + +FUNCTION(codestart) + @ Store context: Machine ID, atags/dtb, ... + @ U-Boot API signature is stored on the U-Boot heap + @ Stack pointer used as start address for signature probing + mov r12, sp + ldr sp, =entry_state + push {r4-r12,lr} @ store U-Boot context (sp in r12) + + @ Put kernel parameters aside until we can store them (further down) + mov r4, r1 @ machine type + mov r5, r2 @ boot data + + @ modules have been stored as a blob in BSS, + @ they need to be manually relocated + @ If everything fits within BSS, good + @ If not, relocate to __bss_start + grub_total_module_size + ldr r0, =__bss_start @ src + ldr r1, =_end @ dst = End of BSS + ldr r2, grub_total_module_size @ blob size + add r3, r0, r2 @ blob end + cmp r1, r3 @ _end < blob end? + movlt r1, r3 @ dst = blob end + blob size + mov r2, r1 @ end = dst + +1: ldr r3, [r0], #4 @ r3 = *src++ + str r3, [r1], #4 @ *dst++ = r3 + cmp r0, r2 @ src == end ? + blt 1b + + @ Set up a new stack, beyond the end of copied modules. + ldr r3, =GRUB_KERNEL_MACHINE_STACK_SIZE + add r3, r1, r3 @ Place stack beyond end of modules + and sp, r3, #~0x7 @ Ensure 8-byte alignment + + @ Since we _are_ the C run-time, we need to manually zero the BSS + @ region before continuing + ldr r0, =__bss_start + ldr r1, =_end + mov r2, #0 +1: str r2, [r0], #4 + cmp r0, r1 + bne 1b + + @ Global variables now accessible - store kernel parameters in memory + ldr r12, =uboot_machine_type + str r4, [r12] + ldr r12, =uboot_boot_data + str r5, [r12] + + b grub_main + + /* + * uboot_syscall(): + * This function is effectively a veneer, so it cannot + * modify the stack or corrupt any registers other than + * r12 (ip). Furthermore it needs to restore r8 for + * U-Boot (Global Data Pointer) and preserve it for Grub. + */ +FUNCTION(uboot_syscall) + ldr ip, =transition_space + stm ip, {r8, lr} + ldr ip, =gd_backup + ldr r8, [ip] + ldr ip, =uboot_syscall_ptr + mov lr, pc + ldr pc, [ip] + ldr ip, =gd_backup + str r8, [ip] + ldr ip, =transition_space + ldm ip, {r8, lr} + bx lr + +FUNCTION(uboot_return) + ldr sp, =entry_state_end + pop {r4-r12, lr} + mov sp, r12 + bx lr + + + .data + .align 3 @ 8-byte alignment for stack +@ U-boot context stack space +entry_state_end: + .long 0 @ r4 + .long 0 @ r5 + .long 0 @ r6 + .long 0 @ r7 +gd_backup: + .long 0 @ r8 - U-Boot global data pointer + .long 0 @ r9 + .long 0 @ r10 + .long 0 @ r11 +VARIABLE(uboot_search_hint)@ U-Boot stack pointer - + .long 0 @ also API signature address hint. + .long 0 @ lr +entry_state: @ backup for U-Boot context + +@ GRUB context stack space +transition_space: + .long 0 @ r8 + .long 0 @ lr + +VARIABLE(uboot_syscall_ptr) + .long 0 @ + + .end === modified file 'grub-core/kern/main.c' --- grub-core/kern/main.c 2012-06-22 09:51:48 +0000 +++ grub-core/kern/main.c 2012-10-22 18:29:17 +0000 @@ -30,8 +30,10 @@ #include #include -/* This is actualy platform-independant but used only on loongson and sparc. */ -#if defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_MIPS_QEMU_MIPS) || defined (GRUB_MACHINE_SPARC64) +/* This is actualy platform-independant but used only on some platforms. */ +#if defined (GRUB_MACHINE_MIPS_LOONGSON) || \ + defined (GRUB_MACHINE_MIPS_QEMU_MIPS) || defined (GRUB_MACHINE_SPARC64) || \ + defined (GRUB_MACHINE_ARM) grub_addr_t grub_modules_get_end (void) { === added directory 'grub-core/kern/uboot' === added file 'grub-core/kern/uboot/glue.c' --- grub-core/kern/uboot/glue.c 1970-01-01 00:00:00 +0000 +++ grub-core/kern/uboot/glue.c 2012-10-22 18:31:19 +0000 @@ -0,0 +1,475 @@ +/* + * (C) Copyright 2007-2008 Semihalf, Rafal Jaworowski + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program 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 2 of + * the License, or (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#include +#include +#include +#include +#include + +extern int uboot_syscall (int, int *, ...); +#define syscall(x, y, ...) uboot_syscall(x, y, __VA_ARGS__) + +typedef grub_uint32_t uint32_t; + +static int +valid_sig (struct api_signature *sig) +{ + uint32_t checksum; + struct api_signature s; + + if (sig == NULL) + return 0; + /* + * Clear the checksum field (in the local copy) so as to calculate the + * CRC with the same initial contents as at the time when the sig was + * produced + */ + s = *sig; + s.checksum = 0; + +#if 0 + checksum = crc32 (&s, sizeof (struct api_signature)); +#else + checksum = sig->checksum; +#endif + + if (checksum != sig->checksum) + return 0; + + return 1; +} + +/* + * Searches for the U-Boot API signature + * + * returns 1/0 depending on found/not found result + */ +int +api_search_sig (struct api_signature **sig) +{ + unsigned char *sp; + uint32_t search_start = 0; + uint32_t search_end = 0; + + if (sig == NULL) + return 0; + + if (uboot_search_hint == 0) + uboot_search_hint = 255 * 1024 * 1024; + + /* Extended search range to work around Trim Slice U-Boot issue */ + search_start = (uboot_search_hint & ~0x000fffff) - 0x00500000; + search_end = search_start + API_SEARCH_LEN - API_SIG_MAGLEN; + search_end += 0x00500000; + + sp = (unsigned char *) search_start; + while ((sp + API_SIG_MAGLEN) < (unsigned char *) search_end) + { + if (!memcmp (sp, API_SIG_MAGIC, API_SIG_MAGLEN)) + { + *sig = (struct api_signature *) (uint32_t) sp; + if (valid_sig (*sig)) + return 1; + } + sp += API_SIG_MAGLEN; + } + + *sig = NULL; + return 0; +} + +/**************************************** + * + * console + * + ****************************************/ + +int +ub_getc (void) +{ + int c; + + if (!syscall (API_GETC, NULL, (uint32_t) & c)) + return -1; + + return c; +} + +int +ub_tstc (void) +{ + int t; + + if (!syscall (API_TSTC, NULL, (uint32_t) & t)) + return -1; + + return t; +} + +void +ub_putc (char c) +{ + syscall (API_PUTC, NULL, (uint32_t) & c); +} + +void +ub_puts (const char *s) +{ + syscall (API_PUTS, NULL, (uint32_t) s); +} + +/**************************************** + * + * system + * + ****************************************/ + +void +ub_reset (void) +{ + syscall (API_RESET, NULL, 0); +} + +static struct mem_region mr[UB_MAX_MR]; +static struct sys_info si; + +struct sys_info * +ub_get_sys_info (void) +{ + int err = 0; + + memset (&si, 0, sizeof (struct sys_info)); + si.mr = mr; + si.mr_no = UB_MAX_MR; + memset (&mr, 0, sizeof (mr)); + + if (!syscall (API_GET_SYS_INFO, &err, (uint32_t) & si)) + return NULL; + + return ((err) ? NULL : &si); +} + +/**************************************** + * + * timing + * + ****************************************/ + +void +ub_udelay (unsigned long usec) +{ + syscall (API_UDELAY, NULL, &usec); +} + +unsigned long +ub_get_timer (unsigned long base) +{ + unsigned long cur; + + if (!syscall (API_GET_TIMER, NULL, &cur, &base)) + return 0; + + return cur; +} + + +/**************************************************************************** + * + * devices + * + * Devices are identified by handles: numbers 0, 1, 2, ..., UB_MAX_DEV-1 + * + ***************************************************************************/ + +static struct device_info devices[UB_MAX_DEV]; + +struct device_info * +ub_dev_get (int i) +{ + return ((i < 0 || i >= UB_MAX_DEV) ? NULL : &devices[i]); +} + +/* + * Enumerates the devices: fills out device_info elements in the devices[] + * array. + * + * returns: number of devices found + */ +int +ub_dev_enum (void) +{ + struct device_info *di; + int n = 0; + + memset (&devices, 0, sizeof (struct device_info) * UB_MAX_DEV); + di = &devices[0]; + + if (!syscall (API_DEV_ENUM, NULL, di)) + return 0; + + while (di->cookie != NULL) + { + + if (++n >= UB_MAX_DEV) + break; + + /* take another device_info */ + di++; + + /* pass on the previous cookie */ + di->cookie = devices[n - 1].cookie; + + if (!syscall (API_DEV_ENUM, NULL, di)) + return 0; + } + + return n; +} + +/* + * handle: 0-based id of the device + * + * returns: 0 when OK, err otherwise + */ +int +ub_dev_open (int handle) +{ + struct device_info *di; + int err = 0; + + if (handle < 0 || handle >= UB_MAX_DEV) + return API_EINVAL; + + di = &devices[handle]; + + if (!syscall (API_DEV_OPEN, &err, di)) + return -1; + + return err; +} + +int +ub_dev_close (int handle) +{ + struct device_info *di; + + if (handle < 0 || handle >= UB_MAX_DEV) + return API_EINVAL; + + di = &devices[handle]; + if (!syscall (API_DEV_CLOSE, NULL, di)) + return -1; + + return 0; +} + +/* + * + * Validates device for read/write, it has to: + * + * - have sane handle + * - be opened + * + * returns: 0/1 accordingly + */ +static int +dev_valid (int handle) +{ + if (handle < 0 || handle >= UB_MAX_DEV) + return 0; + + if (devices[handle].state != DEV_STA_OPEN) + return 0; + + return 1; +} + +static int +dev_stor_valid (int handle) +{ + if (!dev_valid (handle)) + return 0; + + if (!(devices[handle].type & DEV_TYP_STOR)) + return 0; + + return 1; +} + +int +ub_dev_read (int handle, void *buf, lbasize_t len, lbastart_t start, + lbasize_t * rlen) +{ + struct device_info *di; + lbasize_t act_len; + int err = 0; + + if (!dev_stor_valid (handle)) + return API_ENODEV; + + di = &devices[handle]; + if (!syscall (API_DEV_READ, &err, di, buf, &len, &start, &act_len)) + return API_ESYSC; + + if (!err && rlen) + *rlen = act_len; + + return err; +} + +static int +dev_net_valid (int handle) +{ + if (!dev_valid (handle)) + return 0; + + if (devices[handle].type != DEV_TYP_NET) + return 0; + + return 1; +} + +int +ub_dev_recv (int handle, void *buf, int len, int *rlen) +{ + struct device_info *di; + int err = 0, act_len; + + if (!dev_net_valid (handle)) + return API_ENODEV; + + di = &devices[handle]; + if (!syscall (API_DEV_READ, &err, di, buf, &len, &act_len)) + return API_ESYSC; + + if (!err && rlen) + *rlen = act_len; + + return (err); +} + +int +ub_dev_send (int handle, void *buf, int len) +{ + struct device_info *di; + int err = 0; + + if (!dev_net_valid (handle)) + return API_ENODEV; + + di = &devices[handle]; + if (!syscall (API_DEV_WRITE, &err, di, buf, &len)) + return API_ESYSC; + + return err; +} + +/**************************************** + * + * env vars + * + ****************************************/ + +char * +ub_env_get (const char *name) +{ + char *value; + + if (!syscall (API_ENV_GET, NULL, (uint32_t) name, (uint32_t) & value)) + return NULL; + + return value; +} + +void +ub_env_set (const char *name, char *value) +{ + syscall (API_ENV_SET, NULL, (uint32_t) name, (uint32_t) value); +} + +static char env_name[256]; + +const char * +ub_env_enum (const char *last) +{ + const char *env, *str; + int i; + + env = NULL; + + /* + * It's OK to pass only the name piece as last (and not the whole + * 'name=val' string), since the API_ENUM_ENV call uses envmatch() + * internally, which handles such case + */ + if (!syscall (API_ENV_ENUM, NULL, (uint32_t) last, (uint32_t) & env)) + return NULL; + + if (!env) + /* no more env. variables to enumerate */ + return NULL; + + /* next enumerated env var */ + memset (env_name, 0, 256); + for (i = 0, str = env; *str != '=' && *str != '\0';) + env_name[i++] = *str++; + + env_name[i] = '\0'; + + return env_name; +} + +/**************************************** + * + * display + * + ****************************************/ + +int +ub_display_get_info (int type, struct display_info *di) +{ + int err = 0; + + if (!syscall (API_DISPLAY_GET_INFO, &err, (uint32_t) type, (uint32_t) di)) + return API_ESYSC; + + return err; +} + +int +ub_display_draw_bitmap (ulong bitmap, int x, int y) +{ + int err = 0; + + if (!syscall (API_DISPLAY_DRAW_BITMAP, &err, bitmap, x, y)) + return API_ESYSC; + + return err; +} + +void +ub_display_clear (void) +{ + syscall (API_DISPLAY_CLEAR, NULL, 0); +} === added file 'grub-core/kern/uboot/hw.c' --- grub-core/kern/uboot/hw.c 1970-01-01 00:00:00 +0000 +++ grub-core/kern/uboot/hw.c 2012-10-22 18:29:17 +0000 @@ -0,0 +1,114 @@ +/* hw.c - U-Boot hardware discovery */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2012 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 +#include +#include +#include +#include + +grub_addr_t start_of_ram; + +/* The minimal heap size we can live with. */ +#define HEAP_MIN_SIZE (unsigned long) (2 * 1024 * 1024) + +/* + * grub_uboot_probe_memory(): + * Queries U-Boot for available memory regions. + * + * Sets up heap near the image in memory and sets up "start_of_ram". + */ +void +grub_uboot_mm_init (void) +{ + struct sys_info *si = ub_get_sys_info (); + + grub_mm_init_region ((void *) (grub_modules_get_end () + + GRUB_KERNEL_MACHINE_STACK_SIZE), + HEAP_MIN_SIZE); + + if (si && (si->mr_no != 0)) + { + int i; + start_of_ram = GRUB_UINT_MAX; + + for (i = 0; i < si->mr_no; i++) + if ((si->mr[i].flags & MR_ATTR_MASK) == MR_ATTR_DRAM) + if (si->mr[i].start < start_of_ram) + start_of_ram = si->mr[i].start; + } +} + +/* + * grub_uboot_probe_hardware(): + * + */ +grub_err_t +grub_uboot_probe_hardware (void) +{ + int devcount, i; + + devcount = ub_dev_enum (); + grub_dprintf ("init", "%d devices found\n", devcount); + + for (i = 0; i < devcount; i++) + { + struct device_info *devinfo = ub_dev_get (i); + + grub_dprintf ("init", "device handle: %d\n", i); + grub_dprintf ("init", " cookie\t= 0x%08x\n", + (grub_uint32_t) devinfo->cookie); + + if (devinfo->type & DEV_TYP_STOR) + { + grub_dprintf ("init", " type\t\t= DISK\n"); + grub_ubootdisk_register (devinfo, i); + } + else if (devinfo->type & DEV_TYP_NET) + { + grub_dprintf ("init", " type\t\t= NET (not supported yet)\n"); + } + else + { + grub_dprintf ("init", "%s: unknown device type", __FUNCTION__); + } + } + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_machine_mmap_iterate (grub_memory_hook_t hook) +{ + int i; + struct sys_info *si = ub_get_sys_info (); + + if (!si || (si->mr_no < 1)) + return GRUB_ERR_BUG; + + /* Iterate and call `hook'. */ + for (i = 0; i < si->mr_no; i++) + if ((si->mr[i].flags & MR_ATTR_MASK) == MR_ATTR_DRAM) + hook (si->mr[i].start, si->mr[i].size, GRUB_MEMORY_AVAILABLE); + + return GRUB_ERR_NONE; +} === added file 'grub-core/kern/uboot/init.c' --- grub-core/kern/uboot/init.c 1970-01-01 00:00:00 +0000 +++ grub-core/kern/uboot/init.c 2012-10-22 18:29:17 +0000 @@ -0,0 +1,165 @@ +/* init.c - generic U-Boot initialization and finalization */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2012 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 +#include +#include +#include +#include +#include +#include + +extern char __bss_start[]; +extern char _end[]; +extern grub_size_t grub_total_module_size; +extern int (*uboot_syscall_ptr) (int, int *, ...); + +grub_addr_t grub_modbase; + +grub_uint32_t uboot_machine_type; +grub_addr_t uboot_boot_data; + +static unsigned long timer_start; + +grub_uint32_t +uboot_get_machine_type (void) +{ + return uboot_machine_type; +} + +grub_addr_t +uboot_get_boot_data (void) +{ + return uboot_boot_data; +} + +static grub_uint64_t +uboot_timer_ms (void) +{ + return (grub_uint64_t) ub_get_timer (timer_start); +} + +void +grub_machine_init (void) +{ + struct api_signature *sig; + grub_addr_t end; + + /* First of all - establish connection with U-Boot */ + if (!api_search_sig (&sig)) + { + /* Don't even have a console to log errors to... */ + grub_exit (); + } + + uboot_syscall_ptr = sig->syscall; + + if (sig->version > API_SIG_VERSION) + { + /* Try to print an error message */ + ub_puts ("invalid U-Boot API version\n"); + } + + /* + * Modules were relocated to _end, or __bss_start + grub_total_module_size, + * whichever greater. + */ + end = (grub_addr_t) __bss_start + grub_total_module_size; + if (end < (grub_addr_t) _end) + end = (grub_addr_t) _end; + grub_modbase = end; + + /* Initialize the console so that GRUB can display messages. */ + grub_console_init_early (); + + grub_dprintf ("init", "__bss_start: 0x%08x, end: 0x%08x, _end: 0x%08x\n", + (grub_addr_t) __bss_start, + (grub_addr_t) __bss_start + grub_total_module_size, + (grub_addr_t) _end); + grub_dprintf ("init", "grub_modbase: %p\n", (void *) grub_modbase); + grub_dprintf ("init", "grub_modules_get_end(): %p\n", + (void *) grub_modules_get_end ()); + + /* Enumerate memory and initialize the memory management system. */ + grub_uboot_mm_init (); + + /* Initialise full terminfo support */ + grub_console_init_lately (); + + /* Enumerate uboot devices */ + grub_uboot_probe_hardware (); + + /* Initialise timer */ + timer_start = ub_get_timer (0); + grub_install_get_time_ms (uboot_timer_ms); + + /* Initialize */ + grub_ubootdisk_init (); +} + + +void +grub_machine_fini (void) +{ +} + +/* + * grub_machine_get_bootlocation(): + * Called from kern/main.c, which expects a device name (minus parentheses) + * and a filesystem path back, if any are known. + * Any returned values must be pointers to dynamically allocated strings. + */ +void +grub_machine_get_bootlocation (char **device, char **path) +{ + char *tmp; + + tmp = ub_env_get ("grub_bootdev"); + if (tmp) + { + *device = grub_malloc (grub_strlen (tmp) + 1); + if (*device == NULL) + return; + grub_strncpy (*device, tmp, grub_strlen (tmp) + 1); + } + else + *device = NULL; + + tmp = ub_env_get ("grub_bootpath"); + if (tmp) + { + *path = grub_malloc (grub_strlen (tmp) + 1); + if (*path == NULL) + return; + grub_strncpy (*path, tmp, grub_strlen (tmp) + 1); + } + else + *path = NULL; +} + +void +grub_uboot_fini (void) +{ + grub_ubootdisk_fini (); + grub_console_fini (); +} === added file 'grub-core/kern/uboot/uboot.c' --- grub-core/kern/uboot/uboot.c 1970-01-01 00:00:00 +0000 +++ grub-core/kern/uboot/uboot.c 2012-10-22 18:29:17 +0000 @@ -0,0 +1,27 @@ +/* uboot.c - generic U-Boot support */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2012 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 + +void +grub_exit (void) +{ + uboot_return (0); +} === added directory 'grub-core/lib/arm' === added file 'grub-core/lib/arm/libgcc.S' --- grub-core/lib/arm/libgcc.S 1970-01-01 00:00:00 +0000 +++ grub-core/lib/arm/libgcc.S 2012-10-22 18:29:17 +0000 @@ -0,0 +1,299 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2012 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 + + .file "libgcc.S" + .syntax unified +#if !defined (__thumb2__) + .arm +#define ARM(x...) x +#define THUMB(x...) +#else + .thumb +#define THUMB(x...) x +#define ARM(x...) +#endif + + +#ifdef __ARMEB__ +#define al r1 +#define ah r0 +#else +#define al r0 +#define ah r1 +#endif + +GRUB_MOD_LICENSE "GPLv3+" + +/* + * helper functions - __aeabi* with macros imported from Linux kernel: + * linux/arch/arm/lib/lib1funcs.S + * linux/arch/arm/lib/ashldi3.S + * linux/arch/arm/lib/ashrdi3.S + * linux/arch/arm/lib/lshrdi3.S + */ + +/* + * Taken from linux/arch/arm/lib/lib1funcs.S + * Retaining only ARMv5+ code paths + */ +.macro ARM_DIV_BODY dividend, divisor, result, curbit + clz \curbit, \divisor + clz \result, \dividend + sub \result, \curbit, \result + mov \curbit, #1 + mov \divisor, \divisor, lsl \result + mov \curbit, \curbit, lsl \result + mov \result, #0 + + @ Division loop +1: cmp \dividend, \divisor + subhs \dividend, \dividend, \divisor + orrhs \result, \result, \curbit + cmp \dividend, \divisor, lsr #1 + subhs \dividend, \dividend, \divisor, lsr #1 + orrhs \result, \result, \curbit, lsr #1 + cmp \dividend, \divisor, lsr #2 + subhs \dividend, \dividend, \divisor, lsr #2 + orrhs \result, \result, \curbit, lsr #2 + cmp \dividend, \divisor, lsr #3 + subhs \dividend, \dividend, \divisor, lsr #3 + orrhs \result, \result, \curbit, lsr #3 + cmp \dividend, #0 @ Early termination? + movnes \curbit, \curbit, lsr #4 @ No, any more bits to do? + movne \divisor, \divisor, lsr #4 + bne 1b + +.endm + +.macro ARM_DIV2_ORDER divisor, order + clz \order, \divisor + rsb \order, \order, #31 +.endm + +.macro ARM_MOD_BODY dividend, divisor, order, spare + clz \order, \divisor + clz \spare, \dividend + sub \order, \order, \spare + mov \divisor, \divisor, lsl \order + @ Perform all needed substractions to keep only the reminder. + @ Do comparisons in batch of 4 first. + subs \order, \order, #3 @ yes, 3 is intended here + blt 2f + +1: cmp \dividend, \divisor + subhs \dividend, \dividend, \divisor + cmp \dividend, \divisor, lsr #1 + subhs \dividend, \dividend, \divisor, lsr #1 + cmp \dividend, \divisor, lsr #2 + subhs \dividend, \dividend, \divisor, lsr #2 + cmp \dividend, \divisor, lsr #3 + subhs \dividend, \dividend, \divisor, lsr #3 + cmp \dividend, #1 + mov \divisor, \divisor, lsr #4 + subges \order, \order, #4 + bge 1b + + tst \order, #3 + teqne \dividend, #0 + beq 5f + + @ Either 1, 2 or 3 comparison/substractions are left. +2: cmn \order, #2 + blt 4f + beq 3f + cmp \dividend, \divisor + subhs \dividend, \dividend, \divisor + mov \divisor, \divisor, lsr #1 +3: cmp \dividend, \divisor + subhs \dividend, \dividend, \divisor + mov \divisor, \divisor, lsr #1 +4: cmp \dividend, \divisor + subhs \dividend, \dividend, \divisor +5: +.endm + + .text +FUNCTION(__aeabi_uidiv) + subs r2, r1, #1 + moveq pc, lr + bcc Ldiv0 + cmp r0, r1 + bls 11f + tst r1, r2 + beq 12f + + ARM_DIV_BODY r0, r1, r2, r3 + + mov r0, r2 + mov pc, lr + +11: moveq r0, #1 + movne r0, #0 + bx lr + +12: ARM_DIV2_ORDER r1, r2 + + mov r0, r0, lsr r2 + bx lr + +FUNCTION(__aeabi_idiv) + cmp r1, #0 + eor ip, r0, r1 @ save the sign of the result. + beq Ldiv0 + rsbmi r1, r1, #0 @ loops below use unsigned. + subs r2, r1, #1 @ division by 1 or -1 ? + beq 10f + movs r3, r0 + rsbmi r3, r0, #0 @ positive dividend value + cmp r3, r1 + bls 11f + tst r1, r2 @ divisor is power of 2 ? + beq 12f + + ARM_DIV_BODY r3, r1, r0, r2 + + cmp ip, #0 + rsbmi r0, r0, #0 + bx lr + +10: teq ip, r0 @ same sign ? + rsbmi r0, r0, #0 + bx lr + +11: movlo r0, #0 + moveq r0, ip, asr #31 + orreq r0, r0, #1 + bx lr + +12: ARM_DIV2_ORDER r1, r2 + + cmp ip, #0 + mov r0, r3, lsr r2 + rsbmi r0, r0, #0 + bx lr + +FUNCTION(__aeabi_uidivmod) + stmfd sp!, {r0, r1, ip, lr} + bl __aeabi_uidiv + ldmfd sp!, {r1, r2, ip, lr} + mul r3, r0, r2 + sub r1, r1, r3 + bx lr + +FUNCTION(__aeabi_idivmod) + stmfd sp!, {r0, r1, ip, lr} + bl __aeabi_idiv + ldmfd sp!, {r1, r2, ip, lr} + mul r3, r0, r2 + sub r1, r1, r3 + bx lr + +@ (Don't) handle division by 0 +FUNCTION(Ldiv0) + push {r4, lr} + mov r0, #0 @ About as wrong as it could be. + pop {r4, pc} + + +/* + * From linux/arch/arm/lib/?sh*3.S + */ +FUNCTION(__aeabi_lasr) + subs r3, r2, #32 + rsb ip, r2, #32 + movmi al, al, lsr r2 + movpl al, ah, asr r3 + ARM( orrmi al, al, ah, lsl ip ) + THUMB( lslmi r3, ah, ip ) + THUMB( orrmi al, al, r3 ) + mov ah, ah, asr r2 + bx lr + +FUNCTION(__aeabi_llsl) + subs r3, r2, #32 + rsb ip, r2, #32 + movmi ah, ah, lsl r2 + movpl ah, al, lsl r3 + ARM( orrmi ah, ah, al, lsr ip ) + THUMB( lsrmi r3, al, ip ) + THUMB( orrmi ah, ah, r3 ) + mov al, al, lsl r2 + bx lr + +FUNCTION(__aeabi_llsr) + subs r3, r2, #32 + rsb ip, r2, #32 + movmi al, al, lsr r2 + movpl al, ah, lsr r3 + ARM( orrmi al, al, ah, lsl ip ) + THUMB( lslmi r3, ah, ip ) + THUMB( orrmi al, al, r3 ) + mov ah, ah, lsr r2 + bx lr + + +/* + * Simple cache maintenance functions + */ + +@ r0 - *beg (inclusive) +@ r1 - *end (exclusive) +clean_dcache_range: + @DCCMVAU +1: cmp r0, r1 + bge 2f + mcr p15, 0, r0, c7, c11, 1 + add r0, r0, #32 @ assume 32-byte cache line +2: dsb + bx lr + +@ r0 - *beg (inclusive) +@ r1 - *end (exclusive) +invalidate_icache_range: + @ICIMVAU +1: cmp r0, r1 + bge 2f + mcr p15, 0, r0, c7, c5, 1 + @BPIMVA + mcr p15, 0, r0, c7, c5, 7 + add r0, r0, #32 @ assume 32-byte cache line + b 1b + dsb +2: isb + bx lr + address@hidden __clear_cache(char *beg, char *end); +FUNCTION(__clear_cache) + push {r4-r6, lr} + mov r4, r0 + mov r5, r1 + bl clean_dcache_range + mov r0, r4 + mov r1, r5 + bl invalidate_icache_range + pop {r4-r6, pc} + address@hidden grub_arch_sync_caches (void *address, grub_size_t len) +FUNCTION(grub_arch_sync_caches) + add r1, r0, r1 + b __clear_cache + + .end === added file 'grub-core/lib/arm/setjmp.S' --- grub-core/lib/arm/setjmp.S 1970-01-01 00:00:00 +0000 +++ grub-core/lib/arm/setjmp.S 2012-10-22 18:29:17 +0000 @@ -0,0 +1,57 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2012 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 + + .file "setjmp.S" + .syntax unified +#if !defined (__thumb2__) + .arm +#define ARM(x...) x +#define THUMB(x...) +#else + .thumb +#define THUMB(x...) x +#define ARM(x...) +#endif + +GRUB_MOD_LICENSE "GPLv3+" + + .text + +/* + * int grub_setjmp (grub_jmp_buf env) + */ +FUNCTION(grub_setjmp) + THUMB( mov ip, sp ) + THUMB( stm r0, { r4-r11, ip, lr } ) + ARM( stm r0, { r4-r11, sp, lr } ) + mov r0, #0 + bx lr + +/* + * int grub_longjmp (grub_jmp_buf env, int val) + */ +FUNCTION(grub_longjmp) + THUMB( ldm r0, { r4-r11, ip, lr } ) + THUMB( mov sp, ip ) + ARM( ldm r0, { r4-r11, sp, lr } ) + movs r0, r1 + moveq r0, #1 + bx lr === modified file 'grub-core/lib/setjmp.S' --- grub-core/lib/setjmp.S 2012-01-18 13:04:52 +0000 +++ grub-core/lib/setjmp.S 2012-10-22 18:29:17 +0000 @@ -11,6 +11,8 @@ #elif defined(__ia64__) #include "./ia64/setjmp.S" #include "./ia64/longjmp.S" +#elif defined(__arm__) +#include "./arm/setjmp.S" #else #error "Unknown target cpu type" #endif === added directory 'grub-core/lib/uboot' === added file 'grub-core/lib/uboot/datetime.c' --- grub-core/lib/uboot/datetime.c 1970-01-01 00:00:00 +0000 +++ grub-core/lib/uboot/datetime.c 2012-10-22 18:29:17 +0000 @@ -0,0 +1,41 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2012 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 +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +/* No simple platform-independent RTC access exists in U-Boot. */ + +grub_err_t +grub_get_datetime (struct grub_datetime *datetime __attribute__ ((unused))) +{ + return grub_error (GRUB_ERR_INVALID_COMMAND, + "can\'t get datetime using U-Boot"); +} + +grub_err_t +grub_set_datetime (struct grub_datetime * datetime __attribute__ ((unused))) +{ + return grub_error (GRUB_ERR_INVALID_COMMAND, + "can\'t set datetime using U-Boot"); +} === added file 'grub-core/lib/uboot/halt.c' --- grub-core/lib/uboot/halt.c 1970-01-01 00:00:00 +0000 +++ grub-core/lib/uboot/halt.c 2012-10-22 18:29:17 +0000 @@ -0,0 +1,31 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2012 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 + +void +grub_halt (void) +{ + grub_machine_fini (); + + /* Just stop here */ + + while (1); +} === added file 'grub-core/lib/uboot/reboot.c' --- grub-core/lib/uboot/reboot.c 1970-01-01 00:00:00 +0000 +++ grub-core/lib/uboot/reboot.c 2012-10-22 18:29:17 +0000 @@ -0,0 +1,30 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2012 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 + +void +grub_reboot (void) +{ + grub_machine_fini (); + + ub_reset (); + while (1); +} === added directory 'grub-core/loader/arm' === added directory 'grub-core/loader/arm/uboot' === added file 'grub-core/loader/arm/uboot/linux.c' --- grub-core/loader/arm/uboot/linux.c 1970-01-01 00:00:00 +0000 +++ grub-core/loader/arm/uboot/linux.c 2012-10-22 18:29:17 +0000 @@ -0,0 +1,379 @@ +/* linux.c - boot Linux */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2012 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 +#include +#include +#include +#include +#include +#include + +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +static grub_dl_t my_mod; + +static grub_addr_t initrd_start; +static grub_size_t initrd_end; + +static grub_addr_t linux_addr; +static grub_size_t linux_size; + +static char *linux_args; + +static grub_addr_t firmware_boot_data; +static grub_addr_t boot_data; +static grub_uint32_t machine_type; + +/* + * linux_prepare_fdt(): + * Prepares a loaded FDT for being passed to Linux. + * Merges in command line parameters and sets up initrd addresses. + */ +static grub_err_t +linux_prepare_fdt (void) +{ + int node; + int retval; + int tmp_size; + void *tmp_fdt; + + tmp_size = fdt_totalsize ((void *) boot_data) + FDT_ADDITIONAL_ENTRIES_SIZE; + tmp_fdt = grub_malloc (tmp_size); + if (!tmp_fdt) + return GRUB_ERR_OUT_OF_MEMORY; + + fdt_open_into ((void *) boot_data, tmp_fdt, tmp_size); + + /* Find or create '/chosen' node */ + node = fdt_subnode_offset (tmp_fdt, 0, "chosen"); + if (node < 0) + { + grub_printf ("No 'chosen' node in FDT - creating.\n"); + node = fdt_add_subnode (tmp_fdt, 0, "chosen"); + if (node < 0) + goto failure; + } + + grub_printf ("linux_args: '%s'\n", linux_args); + + /* Generate and set command line */ + retval = fdt_setprop (tmp_fdt, node, "bootargs", linux_args, + grub_strlen (linux_args) + 1); + if (retval) + goto failure; + + if (initrd_start && initrd_end) + { + /* + * We're using physical addresses, so even if we have LPAE, we're + * restricted to a 32-bit address space. + */ + grub_uint32_t fdt_initrd_start = cpu_to_fdt32 (initrd_start); + grub_uint32_t fdt_initrd_end = cpu_to_fdt32 (initrd_end); + + grub_dprintf ("loader", "Initrd @ 0x%08x-0x%08x\n", + initrd_start, initrd_end); + + retval = fdt_setprop (tmp_fdt, node, "linux,initrd-start", + &fdt_initrd_start, sizeof (fdt_initrd_start)); + if (retval) + goto failure; + retval = fdt_setprop (tmp_fdt, node, "linux,initrd-end", + &fdt_initrd_end, sizeof (fdt_initrd_end)); + if (retval) + goto failure; + } + + /* Copy updated FDT to its launch location */ + fdt_move (tmp_fdt, (void *) boot_data, fdt_totalsize (tmp_fdt)); + grub_free (tmp_fdt); + fdt_pack ((void *) boot_data); + + grub_dprintf ("loader", "FDT updated for Linux boot\n"); + + return GRUB_ERR_NONE; + +failure: + grub_free (tmp_fdt); + return GRUB_ERR_BAD_ARGUMENT; +} + +static grub_err_t +linux_boot (void) +{ + kernel_entry_t linuxmain; + + grub_arch_sync_caches ((void *) linux_addr, linux_size); + + grub_dprintf ("loader", "Kernel at: 0x%x\n", linux_addr); + + if (!boot_data) + { + if (firmware_boot_data) + { + grub_printf ("Using firmware-supplied boot data @ 0x%08x\n", + firmware_boot_data); + boot_data = firmware_boot_data; + } + else + { + return GRUB_ERR_FILE_NOT_FOUND; + } + } + + grub_dprintf ("loader", "Boot data at: 0x%x\n", boot_data); + + if (fdt32_to_cpu (*(grub_uint32_t *) (boot_data)) == FDT_MAGIC) + { + grub_dprintf ("loader", "FDT @ 0x%08x\n", (grub_addr_t) boot_data); + if (linux_prepare_fdt () != GRUB_ERR_NONE) + { + grub_dprintf ("loader", "linux_prepare_fdt() failed\n"); + return GRUB_ERR_FILE_NOT_FOUND; + } + } + + grub_dprintf ("loader", "Jumping to Linux...\n"); + + /* Boot the kernel. + * Arguments to kernel: + * r0 - 0 + * r1 - machine type (passed from U-Boot) + * r2 - address of DTB or ATAG list + */ + linuxmain = (kernel_entry_t) linux_addr; + linuxmain (0, machine_type, (void *) boot_data); + + return GRUB_ERR_NONE; +} + +/* + * Only support zImage, so no relocations necessary + */ +static grub_err_t +linux_load (const char *filename) +{ + grub_file_t file; + int size; + + file = grub_file_open (filename); + if (!file) + return GRUB_ERR_FILE_NOT_FOUND; + + size = grub_file_size (file); + if (size == 0) + return GRUB_ERR_FILE_READ_ERROR; + + linux_addr = LINUX_ADDRESS; + grub_dprintf ("loader", "Loading Linux to 0x%08x\n", + (grub_addr_t) linux_addr); + + if (grub_file_read (file, (void *) linux_addr, size) != size) + { + grub_printf ("Kernel read failed!\n"); + return GRUB_ERR_FILE_READ_ERROR; + } + + if (*(grub_uint32_t *) (linux_addr + LINUX_ZIMAGE_OFFSET) + != LINUX_ZIMAGE_MAGIC) + { + return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("invalid zImage")); + } + + linux_size = size; + + return GRUB_ERR_NONE; +} + +static grub_err_t +linux_unload (void) +{ + grub_dl_unref (my_mod); + + grub_free (linux_args); + linux_args = NULL; + + initrd_start = initrd_end = 0; + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) +{ + int size, retval; + grub_file_t file; + grub_dl_ref (my_mod); + + if (argc == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); + + file = grub_file_open (argv[0]); + if (!file) + goto fail; + + retval = linux_load (argv[0]); + grub_file_close (file); + if (retval != GRUB_ERR_NONE) + goto fail; + + grub_loader_set (linux_boot, linux_unload, 1); + + size = grub_loader_cmdline_size (argc, argv); + linux_args = grub_malloc (size + sizeof (LINUX_IMAGE)); + if (!linux_args) + goto fail; + + /* Create kernel command line. */ + grub_memcpy (linux_args, LINUX_IMAGE, sizeof (LINUX_IMAGE)); + grub_create_loader_cmdline (argc, argv, + linux_args + sizeof (LINUX_IMAGE) - 1, size); + + return GRUB_ERR_NONE; + +fail: + grub_dl_unref (my_mod); + return grub_errno; +} + +static grub_err_t +grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) +{ + grub_file_t file; + int size; + + if (argc == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); + + file = grub_file_open (argv[0]); + if (!file) + return grub_errno; + + size = grub_file_size (file); + if (size == 0) + goto fail; + + initrd_start = LINUX_INITRD_ADDRESS; + grub_dprintf ("loader", "Loading initrd to 0x%08x\n", + (grub_addr_t) initrd_start); + + if (grub_file_read (file, (void *) initrd_start, size) != size) + goto fail; + + initrd_end = initrd_start + size; + + return GRUB_ERR_NONE; + +fail: + grub_file_close (file); + + return grub_errno; +} + +static void * +load_dtb (const char *path) +{ + grub_file_t dtb; + int size; + void *fdt = NULL; + + dtb = grub_file_open (path); + if (!dtb) + return NULL; + + size = grub_file_size (dtb); + if (size == 0) + goto out; + + fdt = grub_malloc (size); + if (!fdt) + goto out; + + if (grub_file_read (dtb, fdt, size) != size) + { + grub_free (fdt); + fdt = NULL; + goto out; + } + + if (fdt_check_header (fdt) != 0) + { + grub_free (fdt); + fdt = NULL; + } + +out: + grub_file_close (dtb); + + return fdt; +} + +static grub_err_t +grub_cmd_devicetree (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) +{ + void *blob; + + if (argc != 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); + + blob = load_dtb (argv[0]); + if (!blob) + return GRUB_ERR_FILE_NOT_FOUND; + + boot_data = LINUX_FDT_ADDRESS; + grub_dprintf ("loader", "Loading device tree to 0x%08x\n", + (grub_addr_t) boot_data); + fdt_move (blob, (void *) boot_data, fdt_totalsize (blob)); + grub_free (blob); + + return GRUB_ERR_NONE; +} + +static grub_command_t cmd_linux, cmd_initrd, cmd_devicetree; + +GRUB_MOD_INIT (linux) +{ + cmd_linux = grub_register_command ("linux", grub_cmd_linux, + 0, N_("Load Linux.")); + cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd, + 0, N_("Load initrd.")); + cmd_devicetree = grub_register_command ("devicetree", grub_cmd_devicetree, + 0, N_("Load DTB file.")); + my_mod = mod; + firmware_boot_data = uboot_get_boot_data (); + + boot_data = (grub_addr_t) NULL; + machine_type = uboot_get_machine_type (); +} + +GRUB_MOD_FINI (linux) +{ + grub_unregister_command (cmd_linux); + grub_unregister_command (cmd_initrd); + grub_unregister_command (cmd_devicetree); +} === modified file 'grub-core/term/terminfo.c' --- grub-core/term/terminfo.c 2012-09-18 09:52:19 +0000 +++ grub-core/term/terminfo.c 2012-10-22 18:29:17 +0000 @@ -746,7 +746,9 @@ static grub_extcmd_t cmd; -#if defined (GRUB_MACHINE_IEEE1275) || defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_MIPS_QEMU_MIPS) || defined (GRUB_MACHINE_ARC) +#if defined (GRUB_MACHINE_IEEE1275) || defined (GRUB_MACHINE_MIPS_LOONGSON) || \ + defined (GRUB_MACHINE_MIPS_QEMU_MIPS) || defined (GRUB_MACHINE_ARC) || \ + defined (GRUB_MACHINE_UBOOT) void grub_terminfo_init (void) #else GRUB_MOD_INIT(terminfo) === added directory 'grub-core/term/uboot' === added file 'grub-core/term/uboot/console.c' --- grub-core/term/uboot/console.c 1970-01-01 00:00:00 +0000 +++ grub-core/term/uboot/console.c 2012-10-22 18:29:17 +0000 @@ -0,0 +1,143 @@ +/* console.c - console interface layer for U-Boot platforms */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2012 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 +#include +#include +#include + +static void +put (struct grub_term_output *term __attribute__ ((unused)), const int c) +{ + ub_putc (c); +} + +static int +readkey (struct grub_term_input *term __attribute__ ((unused))) +{ + if (ub_tstc () > 0) + return ub_getc (); + + return -1; +} + +static void +uboot_console_setcursor (struct grub_term_output *term + __attribute__ ((unused)), int on + __attribute__ ((unused))) +{ + grub_terminfo_setcursor (term, on); +} + +static grub_err_t +uboot_console_init_input (struct grub_term_input *term) +{ + return grub_terminfo_input_init (term); +} + +extern struct grub_terminfo_output_state uboot_console_terminfo_output; + +static void +uboot_console_dimensions (void) +{ + /* Use a small console by default. */ + if (!uboot_console_terminfo_output.width) + uboot_console_terminfo_output.width = 80; + if (!uboot_console_terminfo_output.height) + uboot_console_terminfo_output.height = 24; +} + +static grub_err_t +uboot_console_init_output (struct grub_term_output *term) +{ + uboot_console_dimensions (); + + grub_terminfo_output_init (term); + + return 0; +} + +struct grub_terminfo_input_state uboot_console_terminfo_input = { + .readkey = readkey +}; + +struct grub_terminfo_output_state uboot_console_terminfo_output = { + .put = put, + .width = 80, + .height = 24 +}; + +static struct grub_term_input uboot_console_term_input = { + .name = "console", + .init = uboot_console_init_input, + .getkey = grub_terminfo_getkey, + .data = &uboot_console_terminfo_input +}; + +static struct grub_term_output uboot_console_term_output = { + .name = "console", + .init = uboot_console_init_output, + .putchar = grub_terminfo_putchar, + .getwh = grub_terminfo_getwh, + .getxy = grub_terminfo_getxy, + .gotoxy = grub_terminfo_gotoxy, + .cls = grub_terminfo_cls, + .setcolorstate = grub_terminfo_setcolorstate, + .setcursor = uboot_console_setcursor, + .flags = GRUB_TERM_CODE_TYPE_ASCII, + .data = &uboot_console_terminfo_output, + .normal_color = GRUB_TERM_DEFAULT_NORMAL_COLOR, + .highlight_color = GRUB_TERM_DEFAULT_HIGHLIGHT_COLOR, +}; + +void +grub_console_init_early (void) +{ + grub_term_register_input ("console", &uboot_console_term_input); + grub_term_register_output ("console", &uboot_console_term_output); +} + + +/* + * grub_console_init_lately(): + * Initializes terminfo formatting by registering terminal type. + * Called after heap has been configured. + * + */ +void +grub_console_init_lately (void) +{ + const char *type; + + /* See if explicitly set by U-Boot environment */ + type = ub_env_get ("grub_term"); + if (!type) + type = "vt100"; + + grub_terminfo_init (); + grub_terminfo_output_register (&uboot_console_term_output, type); +} + +void +grub_console_fini (void) +{ +} === added directory 'include/grub/arm' === added file 'include/grub/arm/linux.h' --- include/grub/arm/linux.h 1970-01-01 00:00:00 +0000 +++ include/grub/arm/linux.h 2012-10-22 18:29:17 +0000 @@ -0,0 +1,34 @@ +/* linux.h - ARM linux specific definitions */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2012 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 . + */ + +#ifndef GRUB_LINUX_CPU_HEADER +#define GRUB_LINUX_CPU_HEADER 1 + +#define LINUX_ZIMAGE_OFFSET 0x24 +#define LINUX_ZIMAGE_MAGIC 0x016f2818 + +#define LINUX_ADDRESS (start_of_ram + 0x8000) +#define LINUX_INITRD_ADDRESS (start_of_ram + 0x02000000) +#define LINUX_FDT_ADDRESS (LINUX_INITRD_ADDRESS - 0x10000) + +#define FDT_ADDITIONAL_ENTRIES_SIZE 0x300 + +typedef void (*kernel_entry_t) (int, unsigned long, void *); + +#endif /* ! GRUB_LINUX_CPU_HEADER */ === added file 'include/grub/arm/time.h' --- include/grub/arm/time.h 1970-01-01 00:00:00 +0000 +++ include/grub/arm/time.h 2012-10-22 18:29:17 +0000 @@ -0,0 +1,29 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2012 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 . + */ + +#ifndef KERNEL_CPU_TIME_HEADER +#define KERNEL_CPU_TIME_HEADER 1 + +static __inline void +grub_cpu_idle (void) +{ + /* FIXME: this can't work until we handle interrupts. */ +/* __asm__ __volatile__ ("wfi"); */ +} + +#endif /* ! KERNEL_CPU_TIME_HEADER */ === added file 'include/grub/arm/types.h' --- include/grub/arm/types.h 1970-01-01 00:00:00 +0000 +++ include/grub/arm/types.h 2012-10-22 18:29:17 +0000 @@ -0,0 +1,34 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2012 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 . + */ + +#ifndef GRUB_TYPES_CPU_HEADER +#define GRUB_TYPES_CPU_HEADER 1 + +/* The size of void *. */ +#define GRUB_TARGET_SIZEOF_VOID_P 4 + +/* The size of long. */ +#define GRUB_TARGET_SIZEOF_LONG 4 + +/* currently only support little-endian. */ +#undef GRUB_TARGET_WORDS_BIGENDIAN + +/* Unaligned accesses only supported if MMU enabled */ +//#define GRUB_HAVE_UNALIGNED_ACCESS 1 + +#endif /* ! GRUB_TYPES_CPU_HEADER */ === added directory 'include/grub/arm/uboot' === added file 'include/grub/arm/uboot/kernel.h' --- include/grub/arm/uboot/kernel.h 1970-01-01 00:00:00 +0000 +++ include/grub/arm/uboot/kernel.h 2012-10-22 18:29:17 +0000 @@ -0,0 +1,31 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2012 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 . + */ + +#ifndef GRUB_KERNEL_MACHINE_HEADER +#define GRUB_KERNEL_MACHINE_HEADER 1 + +#define GRUB_KERNEL_MACHINE_STACK_SIZE 0x40000 + +#ifndef ASM_FILE + +#include +#include + +#endif /* ! ASM_FILE */ + +#endif /* ! GRUB_KERNEL_MACHINE_HEADER */ === modified file 'include/grub/disk.h' --- include/grub/disk.h 2012-02-09 22:15:27 +0000 +++ include/grub/disk.h 2012-10-22 18:29:17 +0000 @@ -27,21 +27,22 @@ /* These are used to set a device id. When you add a new disk device, you must define a new id for it here. */ enum grub_disk_dev_id - { - GRUB_DISK_DEVICE_BIOSDISK_ID, - GRUB_DISK_DEVICE_OFDISK_ID, - GRUB_DISK_DEVICE_LOOPBACK_ID, - GRUB_DISK_DEVICE_EFIDISK_ID, - GRUB_DISK_DEVICE_DISKFILTER_ID, - GRUB_DISK_DEVICE_HOST_ID, - GRUB_DISK_DEVICE_ATA_ID, - GRUB_DISK_DEVICE_MEMDISK_ID, - GRUB_DISK_DEVICE_NAND_ID, - GRUB_DISK_DEVICE_SCSI_ID, - GRUB_DISK_DEVICE_CRYPTODISK_ID, - GRUB_DISK_DEVICE_ARCDISK_ID, - GRUB_DISK_DEVICE_HOSTDISK_ID, - }; +{ + GRUB_DISK_DEVICE_BIOSDISK_ID, + GRUB_DISK_DEVICE_OFDISK_ID, + GRUB_DISK_DEVICE_LOOPBACK_ID, + GRUB_DISK_DEVICE_EFIDISK_ID, + GRUB_DISK_DEVICE_DISKFILTER_ID, + GRUB_DISK_DEVICE_HOST_ID, + GRUB_DISK_DEVICE_ATA_ID, + GRUB_DISK_DEVICE_MEMDISK_ID, + GRUB_DISK_DEVICE_NAND_ID, + GRUB_DISK_DEVICE_SCSI_ID, + GRUB_DISK_DEVICE_CRYPTODISK_ID, + GRUB_DISK_DEVICE_ARCDISK_ID, + GRUB_DISK_DEVICE_HOSTDISK_ID, + GRUB_DISK_DEVICE_UBOOTDISK_ID, +}; struct grub_disk; #ifdef GRUB_UTIL @@ -49,12 +50,12 @@ #endif typedef enum - { - GRUB_DISK_PULL_NONE, - GRUB_DISK_PULL_REMOVABLE, - GRUB_DISK_PULL_RESCAN, - GRUB_DISK_PULL_MAX - } grub_disk_pull_t; +{ + GRUB_DISK_PULL_NONE, + GRUB_DISK_PULL_REMOVABLE, + GRUB_DISK_PULL_RESCAN, + GRUB_DISK_PULL_MAX +} grub_disk_pull_t; /* Disk device. */ struct grub_disk_dev @@ -66,26 +67,25 @@ enum grub_disk_dev_id id; /* Call HOOK with each device name, until HOOK returns non-zero. */ - int (*iterate) (int (*hook) (const char *name), - grub_disk_pull_t pull); + int (*iterate) (int (*hook) (const char *name), grub_disk_pull_t pull); /* Open the device named NAME, and set up DISK. */ - grub_err_t (*open) (const char *name, struct grub_disk *disk); + grub_err_t (*open) (const char *name, struct grub_disk * disk); /* Close the disk DISK. */ - void (*close) (struct grub_disk *disk); + void (*close) (struct grub_disk * disk); /* Read SIZE sectors from the sector SECTOR of the disk DISK into BUF. */ - grub_err_t (*read) (struct grub_disk *disk, grub_disk_addr_t sector, - grub_size_t size, char *buf); + grub_err_t (*read) (struct grub_disk * disk, grub_disk_addr_t sector, + grub_size_t size, char *buf); /* Write SIZE sectors from BUF into the sector SECTOR of the disk DISK. */ - grub_err_t (*write) (struct grub_disk *disk, grub_disk_addr_t sector, - grub_size_t size, const char *buf); + grub_err_t (*write) (struct grub_disk * disk, grub_disk_addr_t sector, + grub_size_t size, const char *buf); #ifdef GRUB_UTIL - struct grub_disk_memberlist *(*memberlist) (struct grub_disk *disk); - const char * (*raidname) (struct grub_disk *disk); + struct grub_disk_memberlist *(*memberlist) (struct grub_disk * disk); + const char *(*raidname) (struct grub_disk * disk); #endif /* The next disk device. */ @@ -121,7 +121,7 @@ /* Called when a sector was read. OFFSET is between 0 and the sector size minus 1, and LENGTH is between 0 and the sector size. */ void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, - unsigned offset, unsigned length); + unsigned offset, unsigned length); /* Device-specific data. */ void *data; @@ -155,8 +155,8 @@ /* This is called from the memory manager. */ void grub_disk_cache_invalidate_all (void); -void EXPORT_FUNC(grub_disk_dev_register) (grub_disk_dev_t dev); -void EXPORT_FUNC(grub_disk_dev_unregister) (grub_disk_dev_t dev); +void EXPORT_FUNC (grub_disk_dev_register) (grub_disk_dev_t dev); +void EXPORT_FUNC (grub_disk_dev_unregister) (grub_disk_dev_t dev); static inline int grub_disk_dev_iterate (int (*hook) (const char *name)) { @@ -171,28 +171,27 @@ return 0; } -grub_disk_t EXPORT_FUNC(grub_disk_open) (const char *name); -void EXPORT_FUNC(grub_disk_close) (grub_disk_t disk); -grub_err_t EXPORT_FUNC(grub_disk_read) (grub_disk_t disk, - grub_disk_addr_t sector, - grub_off_t offset, - grub_size_t size, - void *buf); -grub_err_t EXPORT_FUNC(grub_disk_write) (grub_disk_t disk, +grub_disk_t EXPORT_FUNC (grub_disk_open) (const char *name); +void EXPORT_FUNC (grub_disk_close) (grub_disk_t disk); +grub_err_t EXPORT_FUNC (grub_disk_read) (grub_disk_t disk, grub_disk_addr_t sector, grub_off_t offset, - grub_size_t size, - const void *buf); + grub_size_t size, void *buf); +grub_err_t EXPORT_FUNC (grub_disk_write) (grub_disk_t disk, + grub_disk_addr_t sector, + grub_off_t offset, + grub_size_t size, const void *buf); -grub_uint64_t EXPORT_FUNC(grub_disk_get_size) (grub_disk_t disk); +grub_uint64_t EXPORT_FUNC (grub_disk_get_size) (grub_disk_t disk); #if DISK_CACHE_STATS void -EXPORT_FUNC(grub_disk_cache_get_performance) (unsigned long *hits, unsigned long *misses); +EXPORT_FUNC (grub_disk_cache_get_performance) (unsigned long *hits, + unsigned long *misses); #endif -extern void (* EXPORT_VAR(grub_disk_firmware_fini)) (void); -extern int EXPORT_VAR(grub_disk_firmware_is_tainted); +extern void (*EXPORT_VAR (grub_disk_firmware_fini)) (void); +extern int EXPORT_VAR (grub_disk_firmware_is_tainted); #if defined (GRUB_UTIL) void grub_lvm_init (void); === modified file 'include/grub/elf.h' --- include/grub/elf.h 2012-06-18 19:09:57 +0000 +++ include/grub/elf.h 2012-10-22 18:29:17 +0000 @@ -145,6 +145,7 @@ #define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX. */ #define ELFOSABI_MODESTO 11 /* Novell Modesto. */ #define ELFOSABI_OPENBSD 12 /* OpenBSD. */ +#define ELFOSABI_ARM_AEABI 64 /* ARM EABI */ #define ELFOSABI_ARM 97 /* ARM */ #define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ @@ -2005,15 +2006,18 @@ /* ARM specific declarations */ /* Processor specific flags for the ELF header e_flags field. */ -#define EF_ARM_RELEXEC 0x01 -#define EF_ARM_HASENTRY 0x02 -#define EF_ARM_INTERWORK 0x04 -#define EF_ARM_APCS_26 0x08 -#define EF_ARM_APCS_FLOAT 0x10 -#define EF_ARM_PIC 0x20 -#define EF_ARM_ALIGN8 0x40 /* 8-bit structure alignment is in use */ -#define EF_ARM_NEW_ABI 0x80 -#define EF_ARM_OLD_ABI 0x100 +#define EF_ARM_RELEXEC 0x01 +#define EF_ARM_HASENTRY 0x02 +#define EF_ARM_INTERWORK 0x04 +#define EF_ARM_APCS_26 0x08 +#define EF_ARM_APCS_FLOAT 0x10 +#define EF_ARM_PIC 0x20 +#define EF_ARM_ALIGN8 0x40 /* 8-bit structure alignment is in use */ +#define EF_ARM_NEW_ABI 0x80 +#define EF_ARM_OLD_ABI 0x100 +#define EF_ARM_SOFT_FLOAT 0x200 +#define EF_ARM_VFP_FLOAT 0x400 +#define EF_ARM_MAVERICK_FLOAT 0x800 /* Other constants defined in the ARM ELF spec. version B-01. */ /* NB. These conflict with values defined above. */ @@ -2022,13 +2026,21 @@ #define EF_ARM_MAPSYMSFIRST 0x10 #define EF_ARM_EABIMASK 0XFF000000 +/* Constants defined in AAELF. */ +#define EF_ARM_BE8 0x00800000 +#define EF_ARM_LE8 0x00400000 + #define EF_ARM_EABI_VERSION(flags) ((flags) & EF_ARM_EABIMASK) #define EF_ARM_EABI_UNKNOWN 0x00000000 #define EF_ARM_EABI_VER1 0x01000000 #define EF_ARM_EABI_VER2 0x02000000 +#define EF_ARM_EABI_VER3 0x03000000 +#define EF_ARM_EABI_VER4 0x04000000 +#define EF_ARM_EABI_VER5 0x05000000 /* Additional symbol types for Thumb */ -#define STT_ARM_TFUNC 0xd +#define STT_ARM_TFUNC STT_LOPROC /* A Thumb function. */ +#define STT_ARM_16BIT STT_HIPROC /* A Thumb label. */ /* ARM-specific values for sh_flags */ #define SHF_ARM_ENTRYSECT 0x10000000 /* Section contains an entry point */ @@ -2038,6 +2050,17 @@ /* ARM-specific program header flags */ #define PF_ARM_SB 0x10000000 /* Segment contains the location addressed by the static base */ +#define PF_ARM_PI 0x20000000 /* Position-independent segment. */ +#define PF_ARM_ABS 0x40000000 /* Absolute segment. */ + +/* Processor specific values for the Phdr p_type field. */ +#define PT_ARM_EXIDX (PT_LOPROC + 1) /* ARM unwind segment. */ + +/* Processor specific values for the Shdr sh_type field. */ +#define SHT_ARM_EXIDX (SHT_LOPROC + 1) /* ARM unwind section. */ +#define SHT_ARM_PREEMPTMAP (SHT_LOPROC + 2) /* Preemption details. */ +#define SHT_ARM_ATTRIBUTES (SHT_LOPROC + 3) /* ARM attributes section. */ + /* ARM relocs. */ #define R_ARM_NONE 0 /* No reloc */ @@ -2050,7 +2073,7 @@ #define R_ARM_THM_ABS5 7 #define R_ARM_ABS8 8 /* Direct 8 bit */ #define R_ARM_SBREL32 9 -#define R_ARM_THM_PC22 10 +#define R_ARM_THM_CALL 10 #define R_ARM_THM_PC8 11 #define R_ARM_AMP_VCALL9 12 #define R_ARM_SWI24 13 @@ -2065,16 +2088,36 @@ #define R_ARM_GOTPC 25 /* 32 bit PC relative offset to GOT */ #define R_ARM_GOT32 26 /* 32 bit GOT entry */ #define R_ARM_PLT32 27 /* 32 bit PLT address */ +#define R_ARM_CALL 28 +#define R_ARM_JUMP24 29 +#define R_ARM_THM_JUMP24 30 +#define R_ARM_BASE_ABS 31 #define R_ARM_ALU_PCREL_7_0 32 #define R_ARM_ALU_PCREL_15_8 33 #define R_ARM_ALU_PCREL_23_15 34 #define R_ARM_LDR_SBREL_11_0 35 #define R_ARM_ALU_SBREL_19_12 36 #define R_ARM_ALU_SBREL_27_20 37 +#define R_ARM_TLS_GOTDESC 90 +#define R_ARM_TLS_CALL 91 +#define R_ARM_TLS_DESCSEQ 92 +#define R_ARM_THM_TLS_CALL 93 #define R_ARM_GNU_VTENTRY 100 #define R_ARM_GNU_VTINHERIT 101 #define R_ARM_THM_PC11 102 /* thumb unconditional branch */ #define R_ARM_THM_PC9 103 /* thumb conditional branch */ +#define R_ARM_TLS_GD32 104 /* PC-rel 32 bit for global dynamic + thread local data */ +#define R_ARM_TLS_LDM32 105 /* PC-rel 32 bit for local dynamic + thread local data */ +#define R_ARM_TLS_LDO32 106 /* 32 bit offset relative to TLS + block */ +#define R_ARM_TLS_IE32 107 /* PC-rel 32 bit for GOT entry of + static TLS block offset */ +#define R_ARM_TLS_LE32 108 /* 32 bit offset relative to static + TLS block */ +#define R_ARM_THM_TLS_DESCSEQ 129 +#define R_ARM_IRELATIVE 160 #define R_ARM_RXPC25 249 #define R_ARM_RSBREL32 250 #define R_ARM_THM_RPC22 251 === modified file 'include/grub/libgcc.h' --- include/grub/libgcc.h 2012-02-29 14:28:02 +0000 +++ include/grub/libgcc.h 2012-10-22 18:29:17 +0000 @@ -24,59 +24,59 @@ /* On x86 these functions aren't really needed. Save some space. */ #if !defined (__i386__) && !defined (__x86_64__) -# ifdef HAVE___ASHLDI3 +#ifdef HAVE___ASHLDI3 void EXPORT_FUNC (__ashldi3) (void); -# endif -# ifdef HAVE___ASHRDI3 +#endif +#ifdef HAVE___ASHRDI3 void EXPORT_FUNC (__ashrdi3) (void); -# endif -# ifdef HAVE___LSHRDI3 +#endif +#ifdef HAVE___LSHRDI3 void EXPORT_FUNC (__lshrdi3) (void); -# endif -# ifdef HAVE___UCMPDI2 +#endif +#ifdef HAVE___UCMPDI2 void EXPORT_FUNC (__ucmpdi2) (void); -# endif -# ifdef HAVE___BSWAPSI2 +#endif +#ifdef HAVE___BSWAPSI2 void EXPORT_FUNC (__bswapsi2) (void); -# endif -# ifdef HAVE___BSWAPDI2 +#endif +#ifdef HAVE___BSWAPDI2 void EXPORT_FUNC (__bswapdi2) (void); -# endif -# ifdef HAVE___UDIVSI3 +#endif +#ifdef HAVE___UDIVSI3 void EXPORT_FUNC (__udivsi3) (void); -# endif -# ifdef HAVE___UMODSI3 +#endif +#ifdef HAVE___UMODSI3 void EXPORT_FUNC (__umodsi3) (void); -# endif -# ifdef HAVE___UMODDI3 +#endif +#ifdef HAVE___UMODDI3 void EXPORT_FUNC (__umoddi3) (void); -# endif -# ifdef HAVE___UDIVDI3 +#endif +#ifdef HAVE___UDIVDI3 void EXPORT_FUNC (__udivdi3) (void); -# endif -# ifdef HAVE___MODDI3 +#endif +#ifdef HAVE___MODDI3 void EXPORT_FUNC (__moddi3) (void); -# endif -# ifdef HAVE___DIVDI3 +#endif +#ifdef HAVE___DIVDI3 void EXPORT_FUNC (__divdi3) (void); -# endif -# ifdef HAVE___DIVSI3 +#endif +#ifdef HAVE___DIVSI3 void EXPORT_FUNC (__divsi3) (void); -# endif -# ifdef HAVE___MODSI3 +#endif +#ifdef HAVE___MODSI3 void EXPORT_FUNC (__modsi3) (void); -# endif -# ifdef HAVE___CTZDI2 +#endif +#ifdef HAVE___CTZDI2 void EXPORT_FUNC (__ctzdi2) (void); -# endif -# ifdef HAVE___CTZSI2 +#endif +#ifdef HAVE___CTZSI2 void EXPORT_FUNC (__ctzsi2) (void); -# endif +#endif #endif -# ifdef HAVE___IA64_TRAMPOLINE +#ifdef HAVE___IA64_TRAMPOLINE void EXPORT_FUNC (__ia64_trampoline) (void); -# endif +#endif #ifdef HAVE___TRAMPOLINE_SETUP void EXPORT_FUNC (__trampoline_setup) (void); @@ -120,3 +120,14 @@ void EXPORT_FUNC (_savegpr_30) (void); void EXPORT_FUNC (_savegpr_31) (void); #endif + +#if defined (__arm__) +void EXPORT_FUNC (__aeabi_idiv) (void); +void EXPORT_FUNC (__aeabi_idivmod) (void); +void EXPORT_FUNC (__aeabi_lasr) (void); +void EXPORT_FUNC (__aeabi_llsl) (void); +void EXPORT_FUNC (__aeabi_llsr) (void); +void EXPORT_FUNC (__aeabi_uidiv) (void); +void EXPORT_FUNC (__aeabi_uidivmod) (void); +void EXPORT_FUNC (__clear_cache) (void *, void *); +#endif === modified file 'include/grub/offsets.h' --- include/grub/offsets.h 2012-01-29 22:20:02 +0000 +++ include/grub/offsets.h 2012-10-22 18:29:17 +0000 @@ -102,6 +102,7 @@ #define GRUB_KERNEL_I386_IEEE1275_MOD_GAP 0x0 #define GRUB_KERNEL_I386_COREBOOT_MOD_GAP 0x0 #define GRUB_KERNEL_SPARC64_IEEE1275_MOD_GAP 0x0 +#define GRUB_KERNEL_ARM_UBOOT_MOD_GAP 0x0 #define GRUB_KERNEL_POWERPC_IEEE1275_MOD_ALIGN 0x1000 #define GRUB_KERNEL_SPARC64_IEEE1275_MOD_ALIGN 0x1 @@ -110,6 +111,10 @@ #define GRUB_KERNEL_MIPS_ARC_MOD_ALIGN 0x1 #define GRUB_KERNEL_MIPS_QEMU_MIPS_MOD_ALIGN 0x1 +#define GRUB_KERNEL_ARM_UBOOT_MOD_ALIGN 0x1 +#define GRUB_KERNEL_ARM_UBOOT_TOTAL_MODULE_SIZE 0x4 +#define GRUB_KERNEL_ARM_UBOOT_LINK_ADDR 0x08000000 + /* Minimal gap between _end and the start of the modules. It's a hack for PowerMac to prevent "CLAIM failed" error. The real fix is to rewrite grub-mkimage to generate valid ELF files. */ === modified file 'include/grub/symbol.h' --- include/grub/symbol.h 2012-05-28 15:49:18 +0000 +++ include/grub/symbol.h 2012-10-22 18:29:17 +0000 @@ -29,12 +29,16 @@ #if HAVE_ASM_USCORE #ifdef ASM_FILE -# define EXT_C(sym) _ ## sym -#else -# define EXT_C(sym) "_" sym -#endif -#else -# define EXT_C(sym) sym +#ifndef (__arm__) +#define EXT_C(sym) _ ## sym +#else +#define EXT_C(sym) % ## sym +#endif +#else +#define EXT_C(sym) "_" sym +#endif +#else +#define EXT_C(sym) sym #endif #if defined (__APPLE__) @@ -52,8 +56,8 @@ /* Mark an exported symbol. */ #ifndef GRUB_SYMBOL_GENERATOR -# define EXPORT_FUNC(x) x -# define EXPORT_VAR(x) x +#define EXPORT_FUNC(x) x +#define EXPORT_VAR(x) x #endif /* ! GRUB_SYMBOL_GENERATOR */ #endif /* ! GRUB_SYMBOL_HEADER */ === added directory 'include/grub/uboot' === added file 'include/grub/uboot/api_public.h' --- include/grub/uboot/api_public.h 1970-01-01 00:00:00 +0000 +++ include/grub/uboot/api_public.h 2012-10-22 18:29:17 +0000 @@ -0,0 +1,175 @@ +/* + * (C) Copyright 2007-2008 Semihalf + * + * Written by: Rafal Jaworowski + * + * This file is dual licensed; you can use it under the terms of + * either the GPL, or the BSD license, at your option. + * + * I. GPL: + * + * This file 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 2 of + * the License, or (at your option) any later version. + * + * This file 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * Alternatively, + * + * II. BSD license: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _API_PUBLIC_H_ +#define _API_PUBLIC_H_ + +#define API_EINVAL 1 /* invalid argument(s) */ +#define API_ENODEV 2 /* no device */ +#define API_ENOMEM 3 /* no memory */ +#define API_EBUSY 4 /* busy, occupied etc. */ +#define API_EIO 5 /* I/O error */ +#define API_ESYSC 6 /* syscall error */ + +typedef int (*scp_t)(int, int *, ...); + +typedef grub_uint16_t uint16_t; +typedef grub_uint32_t uint32_t; + +#define API_SIG_VERSION 1 +#define API_SIG_MAGIC "UBootAPI" +#define API_SIG_MAGLEN 8 + +struct api_signature { + char magic[API_SIG_MAGLEN]; /* magic string */ + uint16_t version; /* API version */ + uint32_t checksum; /* checksum of this sig struct */ + scp_t syscall; /* entry point to the API */ +}; + +enum { + API_RSVD = 0, + API_GETC, + API_PUTC, + API_TSTC, + API_PUTS, + API_RESET, + API_GET_SYS_INFO, + API_UDELAY, + API_GET_TIMER, + API_DEV_ENUM, + API_DEV_OPEN, + API_DEV_CLOSE, + API_DEV_READ, + API_DEV_WRITE, + API_ENV_ENUM, + API_ENV_GET, + API_ENV_SET, + API_DISPLAY_GET_INFO, + API_DISPLAY_DRAW_BITMAP, + API_DISPLAY_CLEAR, + API_MAXCALL +}; + +#define MR_ATTR_FLASH 0x0001 +#define MR_ATTR_DRAM 0x0002 +#define MR_ATTR_SRAM 0x0003 +#define MR_ATTR_MASK 0x000f + +struct mem_region { + unsigned long start; + unsigned long size; + int flags; +}; + +struct sys_info { + unsigned long clk_bus; + unsigned long clk_cpu; + unsigned long bar; + struct mem_region *mr; + int mr_no; /* number of memory regions */ +}; + +#undef CONFIG_SYS_64BIT_LBA +#ifdef CONFIG_SYS_64BIT_LBA +typedef u_int64_t lbasize_t; +#else +typedef unsigned long lbasize_t; +#endif +typedef unsigned long lbastart_t; + +#define DEV_TYP_NONE 0x0000 +#define DEV_TYP_NET 0x0001 + +#define DEV_TYP_STOR 0x0002 +#define DT_STOR_IDE 0x0010 +#define DT_STOR_SCSI 0x0020 +#define DT_STOR_USB 0x0040 +#define DT_STOR_MMC 0x0080 +#define DT_STOR_SATA 0x0100 + +#define DEV_STA_CLOSED 0x0000 /* invalid, closed */ +#define DEV_STA_OPEN 0x0001 /* open i.e. active */ + +struct device_info { + int type; + void *cookie; + + union { + struct { + lbasize_t block_count; /* no of blocks */ + unsigned long block_size; /* size of one block */ + } storage; + + struct { + unsigned char hwaddr[6]; + } net; + } info; +#define di_stor info.storage +#define di_net info.net + + int state; +}; + +#define DISPLAY_TYPE_LCD 0x0001 +#define DISPLAY_TYPE_VIDEO 0x0002 + +struct display_info { + int type; + /* screen size in pixels */ + int pixel_width; + int pixel_height; + /* screen size in rows and columns of text */ + int screen_rows; + int screen_cols; +}; + +#endif /* _API_PUBLIC_H_ */ === added file 'include/grub/uboot/console.h' --- include/grub/uboot/console.h 1970-01-01 00:00:00 +0000 +++ include/grub/uboot/console.h 2012-10-22 18:29:17 +0000 @@ -0,0 +1,29 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2012 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 . + */ + +#ifndef GRUB_CONSOLE_MACHINE_HEADER +#define GRUB_CONSOLE_MACHINE_HEADER 1 + +/* Initialize the console system. */ +void grub_console_init_early (void); +void grub_console_init_lately (void); + +/* Exit the console system. */ +void grub_console_fini (void); + +#endif /* ! GRUB_CONSOLE_MACHINE_HEADER */ === added file 'include/grub/uboot/disk.h' --- include/grub/uboot/disk.h 1970-01-01 00:00:00 +0000 +++ include/grub/uboot/disk.h 2012-10-22 18:29:17 +0000 @@ -0,0 +1,44 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2012 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 . + */ + +#ifndef GRUB_UBOOT_DISK_HEADER +#define GRUB_UBOOT_DISK_HEADER 1 + +#include +#include +#include + +void grub_ubootdisk_init (void); +void grub_ubootdisk_fini (void); + +enum disktype +{ cd, fd, hd }; + +struct ubootdisk_data +{ + struct ubootdisk_data *next; + void *cookie; + int handle; + int opencount; + enum disktype type; + grub_uint32_t block_size; +}; + +grub_err_t grub_ubootdisk_register (struct device_info *newdev, int handle); + +#endif /* ! GRUB_UBOOT_DISK_HEADER */ === added file 'include/grub/uboot/glue.h' --- include/grub/uboot/glue.h 1970-01-01 00:00:00 +0000 +++ include/grub/uboot/glue.h 2012-10-22 18:29:17 +0000 @@ -0,0 +1,86 @@ +/* + * (C) Copyright 2007 Semihalf + * + * Written by: Rafal Jaworowski + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program 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 2 of + * the License, or (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +/* + * This is the header file for conveniency wrapper routines (API glue) + */ + +#ifndef _API_GLUE_H_ +#define _API_GLUE_H_ + +#include +typedef grub_uint32_t ulong; + +#define API_SEARCH_LEN (3 * 1024 * 1024) /* 3MB search range */ + +#define UB_MAX_MR 5 /* max mem regions number */ +#define UB_MAX_DEV 6 /* max devices number */ + +extern grub_uint32_t uboot_search_hint; + +int api_search_sig(struct api_signature **sig); + +/* + * The ub_ library calls are part of the application, not U-Boot code! They + * are front-end wrappers that are used by the consumer application: they + * prepare arguments for particular syscall and jump to the low level + * syscall() + */ + +/* console */ +int ub_getc(void); +int ub_tstc(void); +void ub_putc(char c); +void ub_puts(const char *s); + +/* system */ +void EXPORT_FUNC(ub_reset) (void); +struct sys_info * ub_get_sys_info(void); + +/* time */ +void ub_udelay(unsigned long); +unsigned long ub_get_timer(unsigned long); + +/* env vars */ +char * ub_env_get(const char *name); +void ub_env_set(const char *name, char *value); +const char * ub_env_enum(const char *last); + +/* devices */ +int ub_dev_enum(void); +int EXPORT_FUNC(ub_dev_open)(int handle); +int EXPORT_FUNC(ub_dev_close)(int handle); +int ub_dev_read(int handle, void *buf, lbasize_t len, + lbastart_t start, lbasize_t *rlen); +int EXPORT_FUNC(ub_dev_send)(int handle, void *buf, int len); +int EXPORT_FUNC(ub_dev_recv)(int handle, void *buf, int len, int *rlen); +struct device_info * ub_dev_get(int); + +/* display */ +int ub_display_get_info(int type, struct display_info *di); +int ub_display_draw_bitmap(ulong bitmap, int x, int y); +void ub_display_clear(void); + +#endif /* _API_GLUE_H_ */ === added file 'include/grub/uboot/uboot.h' --- include/grub/uboot/uboot.h 1970-01-01 00:00:00 +0000 +++ include/grub/uboot/uboot.h 2012-10-22 18:29:17 +0000 @@ -0,0 +1,41 @@ +/* uboot.h - declare variables and functions for U-Boot support */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2012 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 . + */ + +#ifndef GRUB_UBOOT_UBOOT_HEADER +#define GRUB_UBOOT_UBOOT_HEADER 1 + +#include +#include +#include + +/* Functions. */ +void grub_uboot_mm_init (void); +void grub_uboot_init (void); +void grub_uboot_fini (void); + +void uboot_return (int) __attribute__ ((noreturn)); + +grub_err_t grub_uboot_probe_hardware (void); + +extern grub_addr_t EXPORT_VAR (start_of_ram); + +grub_uint32_t EXPORT_FUNC (uboot_get_machine_type) (void); +grub_addr_t EXPORT_FUNC (uboot_get_boot_data) (void); + +#endif /* ! GRUB_UBOOT_UBOOT_HEADER */ === modified file 'util/grub-install.in' --- util/grub-install.in 2012-09-24 17:50:35 +0000 +++ util/grub-install.in 2012-10-22 18:29:17 +0000 @@ -321,6 +321,8 @@ target=i386-pc fi ;; + x"arm"*) + target="arm-uboot";; *) gettext "Unable to determine your platform. Use --target." ; echo ;; @@ -340,7 +342,7 @@ if [ x$disk_module = xunspecified ]; then disk_module=biosdisk fi -elif [ "${grub_modinfo_platform}" = "ieee1275" ] || [ "${grub_modinfo_platform}" = "efi" ] || [ "${grub_modinfo_platform}" = "arc" ] ; then +elif [ "${grub_modinfo_platform}" = "ieee1275" ] || [ "${grub_modinfo_platform}" = "efi" ] || [ "${grub_modinfo_platform}" = "arc" ] || [ "${grub_modinfo_platform}" = "uboot" ] ; then disk_module= else disk_module=native === modified file 'util/grub-mkimage.c' --- util/grub-mkimage.c 2012-06-26 01:38:10 +0000 +++ util/grub-mkimage.c 2012-10-22 18:29:17 +0000 @@ -69,7 +69,7 @@ IMAGE_SPARC64_AOUT, IMAGE_SPARC64_RAW, IMAGE_I386_IEEE1275, IMAGE_LOONGSON_ELF, IMAGE_QEMU, IMAGE_PPC, IMAGE_YEELOONG_FLASH, IMAGE_FULOONG2F_FLASH, IMAGE_I386_PC_PXE, IMAGE_MIPS_ARC, - IMAGE_QEMU_MIPS_FLASH + IMAGE_QEMU_MIPS_FLASH, IMAGE_UBOOT, } id; enum { @@ -453,6 +453,25 @@ .link_align = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN, .default_compression = COMPRESSION_NONE }, + { + .dirname = "arm-uboot", + .names = { "arm-uboot", NULL }, + .voidp_sizeof = 4, + .bigendian = 0, + .id = IMAGE_UBOOT, + .flags = PLATFORM_FLAGS_NONE, + .total_module_size = GRUB_KERNEL_ARM_UBOOT_TOTAL_MODULE_SIZE, + .decompressor_compressed_size = TARGET_NO_FIELD, + .decompressor_uncompressed_size = TARGET_NO_FIELD, + .decompressor_uncompressed_addr = TARGET_NO_FIELD, + .section_align = 1, + .vaddr_offset = 0, + .link_addr = GRUB_KERNEL_ARM_UBOOT_LINK_ADDR, + .elf_target = EM_ARM, + .mod_gap = GRUB_KERNEL_ARM_UBOOT_MOD_GAP, + .mod_align = GRUB_KERNEL_ARM_UBOOT_MOD_ALIGN, + .link_align = 4 + }, }; #define grub_target_to_host32(x) (grub_target_to_host32_real (image_target, (x))) @@ -1626,12 +1645,18 @@ core_size = program_size + header_size + footer_size; } break; + case IMAGE_UBOOT: + /* Raw image, no header, added below */ + break; } grub_util_write_image (core_img, core_size, out, outname); free (core_img); free (kernel_path); + fflush (out); + fsync (fileno (out)); + while (path_list) { next = path_list->next; @@ -1639,6 +1664,41 @@ free (path_list); path_list = next; } + + /* Add U-Boot header using mkimage command */ + if (image_target->id == IMAGE_UBOOT) + { + char cmdstr[1024]; + const char *arch; + int retval; + + if (image_target->elf_target == EM_ARM) + { + arch = "ARM"; + } + else + { + fprintf(stderr, "%s\n", _("Unsupported U-Boot architecture.")); + return; + } + + retval = snprintf(cmdstr, sizeof(cmdstr), + "mkimage -T kernel -A %s -O Linux -a 0x%08x " \ + "-e 0x%08x -C none -d %s %s.ubt", + arch, (grub_uint32_t)GRUB_KERNEL_ARM_UBOOT_LINK_ADDR, + (grub_uint32_t)GRUB_KERNEL_ARM_UBOOT_LINK_ADDR, + outname, outname); + + if (retval >= sizeof(cmdstr)) + { + fprintf(stderr, "%s\n", _("mkimage command line truncated.")); + return; + } + + retval = system(cmdstr); + if (retval != 0) + fprintf(stderr, "%s\n", _("mkimage command failed.")); + } } @@ -1862,7 +1922,6 @@ if (! fp) grub_util_error (_("cannot open `%s': %s"), arguments.output, strerror (errno)); - free (arguments.output); } if (!arguments.dir) @@ -1882,12 +1941,13 @@ arguments.modules, arguments.memdisk, arguments.config, arguments.image_target, arguments.note, arguments.comp); - fflush (fp); - fsync (fileno (fp)); fclose (fp); if (arguments.dir) free (arguments.dir); + if (arguments.output) + free (arguments.output); + return 0; }