From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from list by lists.gnu.org with archive (Exim 4.71) id 1TQN69-0006Fm-7k for mharc-grub-devel@gnu.org; Mon, 22 Oct 2012 14:51:37 -0400 Received: from eggs.gnu.org ([208.118.235.92]:56668) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TQN5y-0006EX-FS for grub-devel@gnu.org; Mon, 22 Oct 2012 14:51:35 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TQN5o-0005M2-3X for grub-devel@gnu.org; Mon, 22 Oct 2012 14:51:26 -0400 Received: from service88.mimecast.com ([195.130.217.12]:36258) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TQN5n-0005Lu-C8 for grub-devel@gnu.org; Mon, 22 Oct 2012 14:51:16 -0400 Received: from emea-cam-gw2.Emea.Arm.com (fw-tnat.cambridge.arm.com [217.140.96.21]) (Using TLS) by service88.mimecast.com; Mon, 22 Oct 2012 19:51:13 +0100 Received: from [10.1.69.77] (10.1.2.13) by emea-cam-gw2.Emea.Arm.com (10.1.123.64) with Microsoft SMTP Server id 8.2.254.0; Mon, 22 Oct 2012 19:51:11 +0100 Message-ID: <5085959D.4040407@arm.com> Date: Mon, 22 Oct 2012 19:51:09 +0100 From: Leif Lindholm User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:15.0) Gecko/20120827 Thunderbird/15.0 MIME-Version: 1.0 To: grub-devel@gnu.org Subject: [RFC] GRUB port for ARMv7-A U-Boot X-MC-Unique: 112102219511303502 Content-Type: multipart/mixed; boundary="------------000109090103020803060404" X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 3) X-Received-From: 195.130.217.12 X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list Reply-To: The development of GNU GRUB List-Id: The development of GNU GRUB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 22 Oct 2012 18:51:35 -0000 --------------000109090103020803060404 Content-Type: text/plain; charset=WINDOWS-1252; format=flowed Content-Transfer-Encoding: quoted-printable Attached is a stripped-down version of what I have today uploaded to=20 launchpad. The full set can be accessed through bzr branch lp:~leif-lindholm/linaro-grub/arm-uboot Missing from this patch is libfdt and the crc32-functions I mentioned in my previous email, although they have not been stripped from the build= =20 configuration files. This is a port of GRUB to the ARM architecture, running on top of the U-Boot firmware. The "U-Boot API", created by Rafal Jaworowsky , for the FreeBSD Loader provides the hardware interface layer. Console supported on serial port using the termios subsystem. Block device support verified with SDcard and SATA. Usage information: - grub-mkimage generates a kernel with a U-Boot header masquerading it as a Linux kernel. - U-Boot Environment variable grub_bootdev can be used to specify the root device. - Block devices must be initialized by U-Boot before calling GRUB if they a= re to be accessible. (By calling "mmc rescan", "ide reset" or similar.) - New "devicetree" command for loading a .dtb from a filesystem. This has been verified on the following platforms: - ARM Versatile Express (4xCortex-A9) - Marvell Armada XP DB-78460-BP. - Trim Slice Imported code: - The "U-Boot API". - aeabi_* libgcc helper functions from linux/arch/arm/lib. Limitations: - Dynamic linker implemented only for ARMv7-A Thumb instruction set. - Currently runs uncached, with MMU off. - No support for ATAG parsing or rewriting, only supports device tree as a means of passing information to the Linux kernel. (If an ATAG list is passed from U-Boot, it can be passed on unmodified, but the "linux" command will not pass on command line parameters.) - Currently a statically linked kernel, requires RAM at 0x08000000. TODO: - linux.init.arm, linux-initramfs.arm, bootcheck-linux-arm, grub-mkrescue Potential future developments: - Implement networking support. - Make grub kernel a fully relocateable ELF. - Implement chainloader. - Enable caches/MMU. Comments welcome. --------------000109090103020803060404 Content-Type: text/x-patch; name=armv7-uboot-stripped.patch Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="armv7-uboot-stripped.patch" =3D=3D=3D modified file 'Makefile.util.def' --- Makefile.util.def=092012-09-26 12:51:13 +0000 +++ Makefile.util.def=092012-10-22 18:29:17 +0000 @@ -469,6 +469,7 @@ enable =3D mips_loongson; enable =3D ia64_efi; enable =3D powerpc_ieee1275; + enable =3D arm_uboot; }; =20 script =3D { =3D=3D=3D modified file 'conf/Makefile.common' --- conf/Makefile.common=092012-04-18 21:37:25 +0000 +++ conf/Makefile.common=092012-10-22 18:29:17 +0000 @@ -37,6 +37,12 @@ CFLAGS_PLATFORM +=3D -mno-app-regs LDFLAGS_PLATFORM =3D -Wl,-melf64_sparc -mno-relax endif +if COND_arm +# Image entry point always in ARM (A32) state - ensure proper functionalit= y if +# the rest is built for the Thumb (T32) state. + CFLAGS_PLATFORM +=3D -mthumb-interwork -mno-unaligned-access + CCASFLAGS_PLATFORM =3D -Wa,-mimplicit-it=3Dthumb +endif =20 # Other options =20 @@ -58,6 +64,7 @@ if ! COND_i386_multiboot if ! COND_i386_ieee1275 if ! COND_x86_64_efi +if ! COND_arm LDADD_KERNEL +=3D -lgcc endif endif @@ -66,9 +73,14 @@ endif endif endif +endif =20 CFLAGS_KERNEL =3D $(CFLAGS_CPU) $(CFLAGS_PLATFORM) -ffreestanding +if ! COND_arm LDFLAGS_KERNEL =3D $(LDFLAGS_CPU) $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_L= DFLAGS_OLDMAGIC) -static-libgcc +else +LDFLAGS_KERNEL =3D $(LDFLAGS_CPU) $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_L= DFLAGS_OLDMAGIC) +endif CPPFLAGS_KERNEL =3D $(CPPFLAGS_CPU) $(CPPFLAGS_PLATFORM) CCASFLAGS_KERNEL =3D $(CCASFLAGS_CPU) $(CCASFLAGS_PLATFORM) if COND_CYGWIN @@ -108,6 +120,8 @@ CFLAGS_GNULIB =3D -Wno-undef -Wno-sign-compare -Wno-unused -Wno-unused-par= ameter -Wno-redundant-decls -Wno-unreachable-code -Wno-conversion -Wno-old-= style-definition -Wno-unsafe-loop-optimizations CPPFLAGS_GNULIB =3D -I$(top_builddir)/grub-core/gnulib -I$(top_srcdir)/gru= b-core/gnulib =20 +CPPFLAGS_LIBFDT =3D -I$(top_srcdir)/grub-core/lib/libfdt + CFLAGS_POSIX =3D -fno-builtin CPPFLAGS_POSIX =3D -I$(top_srcdir)/grub-core/lib/posix_wrap =20 =3D=3D=3D modified file 'configure.ac' --- configure.ac=092012-09-05 14:09:41 +0000 +++ configure.ac=092012-10-22 18:29:17 +0000 @@ -79,6 +79,9 @@ target_cpu=3Dmips; =09=09machine_CPPFLAGS=3D"$machine_CPPFLAGS -DGRUB_CPU_MIPS=3D1"; =09=09;; + arm*) +=09=09target_cpu=3Darm; +=09=09;; esac =20 # Specify the platform (such as firmware). @@ -99,6 +102,7 @@ mipsel-*) platform=3Dloongson ;; mips-*) platform=3Darc ;; ia64-*) platform=3Defi ;; + arm-*) platform=3Duboot ;; *) AC_MSG_ERROR([unsupported CPU: "$target_cpu"]) ;; esac else @@ -133,6 +137,7 @@ mipsel-yeeloong) platform=3Dloongson ;; mipsel-fuloong) platform=3Dloongson ;; mipsel-loongson) ;; + arm-uboot) platform=3Duboot ;; *-emu) ;; *) AC_MSG_ERROR([platform "$platform" is not supported for target CPU "$= target_cpu"]) ;; esac @@ -164,6 +169,7 @@ multiboot)=09machine_CPPFLAGS=3D"$machine_CPPFLAGS -DGRUB_MACHINE_MULTIB= OOT=3D1" ;; efi)=09=09machine_CPPFLAGS=3D"$machine_CPPFLAGS -DGRUB_MACHINE_EFI=3D1" = ;; ieee1275)=09machine_CPPFLAGS=3D"$machine_CPPFLAGS -DGRUB_MACHINE_IEEE127= 5=3D1" ;; + uboot)=09machine_CPPFLAGS=3D"$machine_CPPFLAGS -DGRUB_MACHINE_UBOOT=3D1"= ;; qemu)=09=09machine_CPPFLAGS=3D"$machine_CPPFLAGS -DGRUB_MACHINE_QEMU=3D1= " ;; pc)=09=09machine_CPPFLAGS=3D"$machine_CPPFLAGS -DGRUB_MACHINE_PCBIOS=3D1= " ;; emu)=09=09machine_CPPFLAGS=3D"$machine_CPPFLAGS -DGRUB_MACHINE_EMU=3D1" = ;; @@ -172,6 +178,7 @@ arc)=09machine_CPPFLAGS=3D"$machine_CPPFLAGS -DGRUB_MACHINE_ARC=3D1" ;; esac case "$target_cpu" in + arm) =09machine_CPPFLAGS=3D"$machine_CPPFLAGS -DGRUB_MACHINE_ARM=3D= 1" ;; mips |mipsel) =09machine_CPPFLAGS=3D"$machine_CPPFLAGS -DGRUB_MACHI= NE_MIPS=3D1" ;; sparc64) machine_CPPFLAGS=3D"$machine_CPPFLAGS -DGRUB_MACHINE_SPARC= 64=3D1" ;; esac @@ -669,7 +676,8 @@ CFLAGS=3D"$TARGET_CFLAGS -nostdlib -Wl,--defsym,___main=3D0x8100 -Wno-erro= r" fi CPPFLAGS=3D"$TARGET_CPPFLAGS" -if test x$target_cpu =3D xi386 || test x$target_cpu =3D xx86_64 ; then + +if test x$target_cpu =3D xi386 || test x$target_cpu =3D xx86_64 || test x$= target_cpu =3D xarm ; then LIBS=3D else LIBS=3D-lgcc @@ -1116,6 +1124,8 @@ AM_CONDITIONAL([COND_mips], [test x$target_cpu =3D xmips -o x$target_cpu = =3D xmipsel]) AM_CONDITIONAL([COND_mipsel], [test x$target_cpu =3D xmipsel]) AM_CONDITIONAL([COND_mipseb], [test x$target_cpu =3D xmips]) +AM_CONDITIONAL([COND_arm], [test x$target_cpu =3D xarm ]) +AM_CONDITIONAL([COND_arm_uboot], [test x$target_cpu =3D xarm -a x$platform= =3D xuboot]) =20 AM_CONDITIONAL([COND_HOST_HURD], [test x$host_kernel =3D xhurd]) AM_CONDITIONAL([COND_HOST_LINUX], [test x$host_kernel =3D xlinux]) @@ -1146,6 +1156,9 @@ if test x${cpudir} =3D xmipsel; then cpudir=3Dmips; fi +if test x${cpudir} =3D xarmel; then + cpudir=3Darm; +fi grub_CHECK_LINK_DIR if test x"$link_dir" =3D xyes ; then AC_CONFIG_LINKS([include/grub/cpu:include/grub/$cpudir]) =3D=3D=3D modified file 'gentpl.py' --- gentpl.py=092012-09-12 06:27:26 +0000 +++ gentpl.py=092012-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" ] =20 GROUPS =3D {} =20 @@ -36,10 +36,12 @@ GROUPS["mips"] =3D [ "mips_loongson", "mips_qemu_mips", "mips_arc" ] GROUPS["sparc64"] =3D [ "sparc64_ieee1275" ] GROUPS["powerpc"] =3D [ "powerpc_ieee1275" ] +GROUPS["arm"] =3D [ "arm_uboot" ] =20 # Groups based on firmware GROUPS["efi"] =3D [ "i386_efi", "x86_64_efi", "ia64_efi" ] GROUPS["ieee1275"] =3D [ "i386_ieee1275", "sparc64_ieee1275", "powerpc_i= eee1275" ] +GROUPS["uboot"] =3D [ "arm_uboot" ] =20 # emu is a special case so many core functionality isn't needed on this pl= atform GROUPS["noemu"] =3D GRUB_PLATFORMS[:]; GROUPS["noemu"].remove("emu") @@ -57,10 +59,13 @@ for i in GROUPS["videoinkernel"]: GROUPS["videomodules"].remove(i) =20 # Similar for terminfo -GROUPS["terminfoinkernel"] =3D ["mips_loongson", "mips_arc", "mips_qemu_mi= ps" ] + GROUPS["ieee1275"]; +GROUPS["terminfoinkernel"] =3D ["mips_loongson", "mips_arc", "mips_qemu_mi= ps" ] + GROUPS["ieee1275"] + GROUPS["uboot"]; GROUPS["terminfomodule"] =3D GRUB_PLATFORMS[:]; for i in GROUPS["terminfoinkernel"]: GROUPS["terminfomodule"].remove(i) =20 +# Flattened Device Trees (FDT) +GROUPS["fdt"] =3D [ "arm_uboot" ] + # Miscelaneous groups schedulded to disappear in future GROUPS["i386_coreboot_multiboot_qemu"] =3D ["i386_coreboot", "i386_multibo= ot", "i386_qemu"] GROUPS["nopc"] =3D GRUB_PLATFORMS[:]; GROUPS["nopc"].remove("i386_pc") =3D=3D=3D modified file 'grub-core/Makefile.am' --- grub-core/Makefile.am=092012-10-12 13:04:02 +0000 +++ grub-core/Makefile.am=092012-10-22 18:29:17 +0000 @@ -143,6 +143,11 @@ KERNEL_HEADER_FILES +=3D $(top_srcdir)/include/grub/efi/disk.h endif =20 +if COND_arm_uboot +KERNEL_HEADER_FILES +=3D $(top_srcdir)/include/grub/uboot/uboot.h +KERNEL_HEADER_FILES +=3D $(top_srcdir)/include/grub/uboot/disk.h +endif + if COND_mips KERNEL_HEADER_FILES +=3D $(top_builddir)/include/grub/cpu/kernel.h endif =3D=3D=3D modified file 'grub-core/Makefile.core.def' --- grub-core/Makefile.core.def=092012-09-08 07:40:24 +0000 +++ grub-core/Makefile.core.def=092012-10-22 18:29:17 +0000 @@ -67,6 +67,9 @@ emu_cflags =3D '$(CFLAGS_GNULIB)'; emu_cppflags =3D '$(CPPFLAGS_GNULIB)'; =20 + arm_uboot_ldflags =3D '-Wl,-Ttext=3D0x08000000'; + arm_uboot_stripflags =3D '--strip-unneeded -K start -R .note -R .comm= ent -R .note.gnu.gold-version'; + i386_pc_startup =3D kern/i386/pc/startup.S; i386_efi_startup =3D kern/i386/efi/startup.S; x86_64_efi_startup =3D kern/x86_64/efi/startup.S; @@ -77,6 +80,7 @@ mips_startup =3D kern/mips/startup.S; sparc64_ieee1275_startup =3D kern/sparc64/ieee1275/crt0.S; powerpc_ieee1275_startup =3D kern/powerpc/ieee1275/startup.S; + arm_uboot_startup =3D kern/arm/uboot/startup.S; =20 common =3D kern/command.c; common =3D kern/corecmd.c; @@ -199,6 +203,17 @@ sparc64_ieee1275 =3D kern/sparc64/dl.c; sparc64_ieee1275 =3D kern/sparc64/ieee1275/ieee1275.c; =20 + uboot =3D disk/uboot/ubootdisk.c; + uboot =3D kern/uboot/uboot.c; + uboot =3D kern/uboot/glue.c; + uboot =3D kern/uboot/crc32.c; + uboot =3D kern/uboot/init.c; + uboot =3D kern/uboot/hw.c; + uboot =3D term/uboot/console.c; + + arm =3D kern/arm/dl.c; + arm =3D lib/arm/libgcc.S; + emu =3D disk/host.c; emu =3D gnulib/progname.c; emu =3D gnulib/error.c; @@ -595,6 +610,8 @@ module =3D { name =3D cat; common =3D commands/cat.c; + arm =3D lib/arg.c; + arm =3D commands/extcmd.c; }; =20 module =3D { @@ -665,6 +682,7 @@ efi =3D lib/efi/halt.c; ieee1275 =3D lib/ieee1275/halt.c; emu =3D lib/emu/halt.c; + uboot =3D lib/uboot/halt.c; }; =20 module =3D { @@ -678,6 +696,7 @@ mips_arc =3D lib/mips/arc/reboot.c; mips_loongson =3D lib/mips/loongson/reboot.c; mips_qemu_mips =3D lib/mips/qemu_mips/reboot.c; + uboot =3D lib/uboot/reboot.c; common =3D commands/reboot.c; }; =20 @@ -1300,6 +1319,7 @@ name =3D datetime; cmos =3D lib/cmos_datetime.c; efi =3D lib/efi/datetime.c; + uboot =3D lib/uboot/datetime.c; sparc64_ieee1275 =3D lib/ieee1275/datetime.c; powerpc_ieee1275 =3D lib/ieee1275/datetime.c; sparc64_ieee1275 =3D lib/ieee1275/cmos.c; @@ -1319,6 +1339,7 @@ extra_dist =3D lib/powerpc/setjmp.S; extra_dist =3D lib/ia64/setjmp.S; extra_dist =3D lib/ia64/longjmp.S; + extra_dist =3D lib/arm/setjmp.S; }; =20 module =3D { @@ -1389,6 +1410,19 @@ enable =3D x86; }; =20 +library =3D { + name =3D libfdtlib.a; + common =3D lib/libfdt/fdt.c; + common =3D lib/libfdt/fdt_ro.c; + common =3D lib/libfdt/fdt_rw.c; + common =3D lib/libfdt/fdt_strerror.c; + common =3D lib/libfdt/fdt_sw.c; + common =3D lib/libfdt/fdt_wip.c; + cppflags =3D '$(CPPFLAGS_LIBFDT)'; + + enable =3D arm; +}; + module =3D { name =3D linux; x86 =3D loader/i386/linux.c; @@ -1397,8 +1431,12 @@ powerpc_ieee1275 =3D loader/powerpc/ieee1275/linux.c; sparc64_ieee1275 =3D loader/sparc64/ieee1275/linux.c; ia64_efi =3D loader/ia64/efi/linux.c; + arm_uboot =3D loader/arm/uboot/linux.c; common =3D lib/cmdline.c; enable =3D noemu; + + fdt_cppflags =3D '$(CPPFLAGS_LIBFDT)'; + fdt_ldadd =3D libfdtlib.a; }; =20 module =3D { =3D=3D=3D added directory 'grub-core/disk/uboot' =3D=3D=3D added file 'grub-core/disk/uboot/ubootdisk.c' --- grub-core/disk/uboot/ubootdisk.c=091970-01-01 00:00:00 +0000 +++ grub-core/disk/uboot/ubootdisk.c=092012-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 initializati= on + * 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 =3D hd; + break; + case DT_STOR_MMC: + case DT_STOR_USB: + /* fd */ + type =3D fd; + break; + default: + return GRUB_ERR_BAD_DEVICE; + break; + } + + d =3D (struct ubootdisk_data *) grub_malloc (sizeof (struct ubootdisk_da= ta)); + if (!d) + return GRUB_ERR_OUT_OF_MEMORY; + d->handle =3D handle; + d->cookie =3D newdev->cookie; + d->opencount =3D 0; + + switch (type) + { + case cd: + grub_dprintf ("ubootdisk", "registering cd device\n"); + d->next =3D cd_devices; + cd_devices =3D d; + + break; + case fd: + grub_dprintf ("ubootdisk", "registering fd device\n"); + d->next =3D fd_devices; + fd_devices =3D d; + + break; + case hd: + grub_dprintf ("ubootdisk", "registering hd device\n"); + d->next =3D hd_devices; + hd_devices =3D 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 =3D hd_devices, count =3D 0; d; d =3D d->next, count++) +=09{ +=09 grub_snprintf (buf, sizeof (buf) - 1, "hd%d", count); +=09 grub_dprintf ("ubootdisk", "iterating %s\n", buf); +=09 if (hook (buf)) +=09 return 1; +=09} + break; + case GRUB_DISK_PULL_REMOVABLE: + /* "floppy" - removable mass storage */ + for (d =3D fd_devices, count =3D 0; d; d =3D d->next, count++) +=09{ +=09 grub_snprintf (buf, sizeof (buf) - 1, "fd%d", count); +=09 grub_dprintf ("ubootdisk", "iterating %s\n", buf); +=09 if (hook (buf)) +=09 return 1; +=09} + + /* "cdrom" - removeable read-only storage */ + for (d =3D cd_devices, count =3D 0; d; d =3D d->next, count++) +=09{ +=09 grub_snprintf (buf, sizeof (buf) - 1, "cd%d", count); +=09 grub_dprintf ("ubootdisk", "iterating %s\n", buf); +=09 if (hook (buf)) +=09 return 1; +=09} + 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 =3D devices; d && num; d =3D d->next, num--) + ; + + if (num =3D=3D 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 =3D grub_strtoul (name + 2, 0, 10); + if (grub_errno !=3D GRUB_ERR_NONE) + { + grub_dprintf ("ubootdisk", "Opening '%s' failed, invalid number\n", +=09=09 name); + goto fail; + } + + if (name[1] !=3D 'd') + { + grub_dprintf ("ubootdisk", "Opening '%s' failed, invalid name\n", na= me); + goto fail; + } + + switch (name[0]) + { + case 'f': + d =3D get_device (fd_devices, num); + break; + case 'c': + d =3D get_device (cd_devices, num); + break; + case 'h': + d =3D 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 =3D 0; + } + else + { + retval =3D ub_dev_open (d->handle); + if (retval !=3D 0) +=09goto fail; + d->opencount =3D 1; + } + + grub_dprintf ("ubootdisk", "cookie: 0x%08x\n", (grub_addr_t) d->cookie); + disk->id =3D (grub_addr_t) d->cookie; + + /* Device has previously been enumerated, so this should never fail */ + if ((devinfo =3D ub_dev_get (d->handle)) =3D=3D NULL) + goto fail; + + d->block_size =3D devinfo->di_stor.block_size; + if (d->block_size =3D=3D 0) + { + grub_printf ("%s: no block size!\n", __FUNCTION__); + return GRUB_ERR_IO; + } + + for (disk->log_sector_size =3D 0; + (1U << disk->log_sector_size) < d->block_size; + disk->log_sector_size++); + + grub_dprintf ("ubootdisk", "(%s) blocksize=3D%d, log_sector_size=3D%d\n"= , +=09=09disk->name, d->block_size, disk->log_sector_size); + + disk->total_sectors =3D GRUB_DISK_SIZE_UNKNOWN; + disk->data =3D 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 =3D disk->data; + + /* + * In mirror of open function, keep track of number of calls to close an= d + * 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 =3D=3D 1) + { + retval =3D 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 t= he + * disk cache. Maps directly on top of U-Boot API, only wrap in some err= or + * handling. + */ +static grub_err_t +uboot_disk_read (struct grub_disk *disk, +=09=09 grub_disk_addr_t offset, grub_size_t numblocks, char *buf) +{ + struct ubootdisk_data *d; + lbasize_t real_size; + int retval; + + d =3D disk->data; + + retval =3D ub_dev_read (d->handle, buf, numblocks, offset, &real_size); + grub_dprintf ("ubootdisk", +=09=09"retval=3D%d, numblocks=3D%d, real_size=3D%llu, sector=3D%llu\n", +=09=09retval, numblocks, (grub_uint64_t) real_size, +=09=09(grub_uint64_t) offset); + if (retval !=3D 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)), +=09=09 grub_disk_addr_t sector __attribute__ ((unused)), +=09=09 grub_size_t size __attribute__ ((unused)), +=09=09 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 =3D { + .name =3D "ubootdisk", + .id =3D GRUB_DISK_DEVICE_UBOOTDISK_ID, + .iterate =3D uboot_disk_iterate, + .open =3D uboot_disk_open, + .close =3D uboot_disk_close, + .read =3D uboot_disk_read, + .write =3D uboot_disk_write, + .next =3D 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); +} =3D=3D=3D added directory 'grub-core/kern/arm' =3D=3D=3D added file 'grub-core/kern/arm/dl.c' --- grub-core/kern/arm/dl.c=091970-01-01 00:00:00 +0000 +++ grub-core/kern/arm/dl.c=092012-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 STRT= AB + * section in the module (which is where symbol names are in the objects I= 've + * inspected manually).=20 + */ +static void +set_symstrtab (Elf_Ehdr * e) +{ + int i; + Elf_Shdr *s; + + symstrtab =3D NULL; + + for (i =3D 0, s =3D (Elf_Shdr *) ((grub_uint32_t) e + e->e_shoff); + i < e->e_shnum; + i++, s =3D (Elf_Shdr *) ((grub_uint32_t) s + e->e_shentsize)) + if (s->sh_type =3D=3D SHT_STRTAB) + symstrtab =3D (void *) ((grub_addr_t) e + s->sh_offset); +} + +static const char * +get_symbolname (Elf_Sym * sym) +{ + const char *symbolname =3D 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", +=09 __FUNCTION__, (grub_addr_t) addr, +=09 get_symbolname (sym), sym->st_value); +#endif + + *addr +=3D 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 =3D (*addr << 16) | *(addr + 1); + insmask =3D 0xf800d000; + + /* B.W/BL or BLX? Affects range and expected target state */ + if (((insword >> 12) & 0xd) =3D=3D 0xc) + is_blx =3D 1; + else + is_blx =3D 0; + + offset_low =3D -16777216; + offset_high =3D is_blx ? 16777212 : 16777214; + +#ifdef DL_DEBUG + grub_printf ("%s: %s @ 0x%08x -> %s @ 0x%08x\n", +=09 __FUNCTION__, is_blx ? "BLX" : "B(L)", +=09 (grub_addr_t) addr, get_symbolname (sym), sym->st_value); +#endif + + /* Extract bitfields from instruction words */ + sign =3D (insword >> 26) & 1; + j1 =3D (insword >> 13) & 1; + j2 =3D (insword >> 11) & 1; + offset =3D (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 -=3D 0x02000000; + offset +=3D sym->st_value - (grub_uint32_t) addr; + + if ((offset < offset_low) || (offset > offset_high)) + return grub_error (GRUB_ERR_OUT_OF_RANGE, +=09=09 N_("offset %d (0x%08x) is out of range"), +=09=09 offset, offset); + + /* If BLX, target symbol must be ARM (target address LSB =3D=3D 0) */ + if (is_blx && (offset & 1)) + return grub_error + (GRUB_ERR_BUG, N_("Relocation targeting wrong execution state")); + + /* Reassemble instruction word */ + sign =3D (offset >> 24) & 1; + j1 =3D sign ^ (~(offset >> 23) & 1); + j2 =3D sign ^ (~(offset >> 22) & 1); + insword =3D (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 =3D (insword >> 16) & 0xffff; + *(grub_uint16_t *) (addr + 1) =3D 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 =3D seg->next) + if (seg->section =3D=3D sh_info) + return seg; + + return NULL; +} + +/* + * do_relocations(): + * Iterate over all relocations in section, calling appropriate function= s + * 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 =3D relhdr->sh_size / sizeof (Elf_Rel); + + /* Find the target segment for this relocation section. */ + seg =3D find_segment (mod->segment, relhdr->sh_info); + if (!seg) + return grub_error (GRUB_ERR_EOF, N_("relocation segment not found")); + + rel =3D (Elf_Rel *) ((grub_addr_t) e + relhdr->sh_offset); + + /* Step through all relocations */ + for (i =3D 0, sym =3D mod->symtab; i < entnum; i++) + { + Elf_Word *addr; + int relsym, reltype; + grub_err_t retval; + + if (seg->size < rel[i].r_offset) +=09return grub_error (GRUB_ERR_BAD_MODULE, +=09=09=09 "reloc offset is out of the segment"); + relsym =3D ELF_R_SYM (rel[i].r_info); + reltype =3D ELF_R_TYPE (rel[i].r_info); + addr =3D (Elf_Word *) ((grub_addr_t) seg->addr + rel[i].r_offset); + + switch (reltype) +=09{ +=09case R_ARM_ABS32: +=09 { +=09 /* Data will be naturally aligned */ +=09 retval =3D reloc_abs32 (addr, &sym[relsym]); +=09 if (retval !=3D GRUB_ERR_NONE) +=09 return retval; +=09 } +=09 break; +=09case R_ARM_THM_CALL: +=09case R_ARM_THM_JUMP24: +=09 { +=09 /* Thumb instructions can be 16-bit aligned */ +=09 retval =3D reloc_thm_call ((grub_uint16_t *) addr, &sym[relsym]); +=09 if (retval !=3D GRUB_ERR_NONE) +=09 return retval; +=09 } +=09 break; +=09default: +=09 return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, +=09=09=09 N_("relocation 0x%x is not implemented yet"), +=09=09=09 reltype); +=09} + } + + 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 =3D ehdr; + + /* Check the magic numbers. */ + if (e->e_ident[EI_CLASS] !=3D ELFCLASS32 + || e->e_ident[EI_DATA] !=3D ELFDATA2LSB || e->e_machine !=3D EM_ARM) + return grub_error (GRUB_ERR_BAD_OS, +=09=09 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 =3D 0, s =3D (Elf_Shdr *) ((grub_uint32_t) e + e->e_shoff); + i < e->e_shnum; + i++, s =3D (Elf_Shdr *) ((grub_uint32_t) s + e->e_shentsize)) + if (s->sh_type =3D=3D 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 =3D 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 =3D 0, s =3D FIRST_SHDR (e); i < e->e_shnum; i++, s =3D NEXT_SHDR= (e, s)) + { + grub_err_t ret; + + switch (s->sh_type) +=09{ +=09case SHT_REL: +=09 { +=09 /* Relocations, no addends */ +=09 ret =3D do_relocations (s, e, mod); +=09 if (ret !=3D GRUB_ERR_NONE) +=09 return ret; +=09 } +=09 break; +=09case SHT_NULL: +=09case SHT_PROGBITS: +=09case SHT_SYMTAB: +=09case SHT_STRTAB: +=09case SHT_NOBITS: +=09case SHT_ARM_ATTRIBUTES: +=09 break; +=09case SHT_RELA: +=09default: +=09 { +=09 grub_printf ("unhandled section_type: %d (0x%08x)\n", +=09=09=09 s->sh_type, s->sh_type); +=09 return GRUB_ERR_NOT_IMPLEMENTED_YET; +=09 }; +=09} + } + +#undef FIRST_SHDR +#undef NEXT_SHDR + + return GRUB_ERR_NONE; +} =3D=3D=3D added directory 'grub-core/kern/arm/uboot' =3D=3D=3D added file 'grub-core/kern/arm/uboot/startup.S' --- grub-core/kern/arm/uboot/startup.S=091970-01-01 00:00:00 +0000 +++ grub-core/kern/arm/uboot/startup.S=092012-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. + * : =20 + * : + */ +=09 +=09.text +=09.arm +FUNCTION(_start) +.extern __bss_start +.extern _end +.extern uboot_machine_type +.extern uboot_boot_data +=09b=09codestart +=09 +=09@ Size of final image integrated module blob - set by grub-mkimage +=09. =3D _start + GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE +VARIABLE(grub_total_module_size) +=09.long =090 + +FUNCTION(codestart) +=09@ Store context: Machine ID, atags/dtb, ... +=09@ U-Boot API signature is stored on the U-Boot heap +=09@ Stack pointer used as start address for signature probing +=09mov=09r12, sp +=09ldr=09sp, =3Dentry_state +=09push=09{r4-r12,lr}=09@ store U-Boot context (sp in r12) + +=09@ Put kernel parameters aside until we can store them (further down) +=09mov=09r4, r1=09=09@ machine type +=09mov=09r5, r2=09=09@ boot data + +=09@ modules have been stored as a blob in BSS, +=09@ they need to be manually relocated +=09@ If everything fits within BSS, good +=09@ If not, relocate to __bss_start + grub_total_module_size +=09ldr=09r0, =3D__bss_start=09=09@ src +=09ldr=09r1, =3D_end=09=09=09@ dst =3D End of BSS +=09ldr=09r2, grub_total_module_size=09@ blob size +=09add=09r3, r0, r2=09=09=09@ blob end +=09cmp=09r1, r3=09=09=09=09@ _end < blob end? +=09movlt=09r1, r3=09=09=09=09@ dst =3D blob end + blob size +=09mov=09r2, r1=09=09=09=09@ end =3D dst +=09 +1:=09ldr=09r3, [r0], #4 =09=09=09@ r3 =3D *src++=20 +=09str=09r3, [r1], #4=09=09=09@ *dst++ =3D r3=20 +=09cmp=09r0, r2=09=09=09=09@ src =3D=3D end ? +=09blt=091b +=09 +=09@ Set up a new stack, beyond the end of copied modules. +=09ldr=09r3, =3DGRUB_KERNEL_MACHINE_STACK_SIZE +=09add=09r3, r1, r3=09@ Place stack beyond end of modules +=09and=09sp, r3, #~0x7=09@ Ensure 8-byte alignment + +=09@ Since we _are_ the C run-time, we need to manually zero the BSS +=09@ region before continuing +=09ldr=09r0, =3D__bss_start +=09ldr=09r1, =3D_end +=09mov=09r2, #0 +1:=09str=09r2, [r0], #4 +=09cmp=09r0, r1 +=09bne=091b + +=09@ Global variables now accessible - store kernel parameters in memory +=09ldr r12, =3Duboot_machine_type +=09str r4, [r12] +=09ldr r12, =3Duboot_boot_data +=09str r5, [r12] +=09 +=09b=09grub_main + +=09/* +=09 * uboot_syscall(): +=09 * This function is effectively a veneer, so it cannot +=09 * modify the stack or corrupt any registers other than +=09 * r12 (ip). Furthermore it needs to restore r8 for +=09 * U-Boot (Global Data Pointer) and preserve it for Grub. +=09 */ +FUNCTION(uboot_syscall) +=09ldr=09ip, =3Dtransition_space +=09stm=09ip, {r8, lr} +=09ldr=09ip, =3Dgd_backup +=09ldr=09r8, [ip] +=09ldr=09ip, =3Duboot_syscall_ptr +=09mov=09lr, pc +=09ldr=09pc, [ip] +=09ldr=09ip, =3Dgd_backup +=09str=09r8, [ip] +=09ldr=09ip, =3Dtransition_space +=09ldm=09ip, {r8, lr} +=09bx=09lr +=09 +FUNCTION(uboot_return) +=09ldr=09sp, =3Dentry_state_end +=09pop=09{r4-r12, lr} +=09mov=09sp, r12 +=09bx=09lr + +=09 +=09.data +=09.align=093=09@ 8-byte alignment for stack +@ U-boot context stack space +entry_state_end:=09 +=09.long=090=09@ r4 +=09.long=090=09@ r5 +=09.long=090=09@ r6 +=09.long=090=09@ r7 +gd_backup:=09 +=09.long=090=09@ r8 - U-Boot global data pointer +=09.long=090=09@ r9 +=09.long=090=09@ r10 +=09.long=090=09@ r11 +VARIABLE(uboot_search_hint)@ U-Boot stack pointer -=20 +=09.long=090=09@ also API signature address hint. +=09.long=090=09@ lr +entry_state:=09=09@ backup for U-Boot context + +@ GRUB context stack space +transition_space:=09 +=09.long=090=09@ r8 +=09.long=090=09@ lr + +VARIABLE(uboot_syscall_ptr) +=09.long=090=09@ + +=09.end =3D=3D=3D modified file 'grub-core/kern/main.c' --- grub-core/kern/main.c=092012-06-22 09:51:48 +0000 +++ grub-core/kern/main.c=092012-10-22 18:29:17 +0000 @@ -30,8 +30,10 @@ #include #include =20 -/* This is actualy platform-independant but used only on loongson and spar= c. */ -#if defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_MIPS_QEM= U_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) { =3D=3D=3D added directory 'grub-core/kern/uboot' =3D=3D=3D added file 'grub-core/kern/uboot/glue.c' --- grub-core/kern/uboot/glue.c=091970-01-01 00:00:00 +0000 +++ grub-core/kern/uboot/glue.c=092012-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.=09 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 =3D=3D 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 =3D *sig; + s.checksum =3D 0; + +#if 0 + checksum =3D crc32 (&s, sizeof (struct api_signature)); +#else + checksum =3D sig->checksum; +#endif + + if (checksum !=3D 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 =3D 0; + uint32_t search_end =3D 0; + + if (sig =3D=3D NULL) + return 0; + + if (uboot_search_hint =3D=3D 0) + uboot_search_hint =3D 255 * 1024 * 1024; + + /* Extended search range to work around Trim Slice U-Boot issue */ + search_start =3D (uboot_search_hint & ~0x000fffff) - 0x00500000; + search_end =3D search_start + API_SEARCH_LEN - API_SIG_MAGLEN; + search_end +=3D 0x00500000; + + sp =3D (unsigned char *) search_start; + while ((sp + API_SIG_MAGLEN) < (unsigned char *) search_end) + { + if (!memcmp (sp, API_SIG_MAGIC, API_SIG_MAGLEN)) +=09{ +=09 *sig =3D (struct api_signature *) (uint32_t) sp; +=09 if (valid_sig (*sig)) +=09 return 1; +=09} + sp +=3D API_SIG_MAGLEN; + } + + *sig =3D 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 =3D 0; + + memset (&si, 0, sizeof (struct sys_info)); + si.mr =3D mr; + si.mr_no =3D 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 >=3D UB_MAX_DEV) ? NULL : &devices[i]); +} + +/* + * Enumerates the devices: fills out device_info elements in the devices[] + * array. + * + * returns:=09=09number of devices found + */ +int +ub_dev_enum (void) +{ + struct device_info *di; + int n =3D 0; + + memset (&devices, 0, sizeof (struct device_info) * UB_MAX_DEV); + di =3D &devices[0]; + + if (!syscall (API_DEV_ENUM, NULL, di)) + return 0; + + while (di->cookie !=3D NULL) + { + + if (++n >=3D UB_MAX_DEV) +=09break; + + /* take another device_info */ + di++; + + /* pass on the previous cookie */ + di->cookie =3D devices[n - 1].cookie; + + if (!syscall (API_DEV_ENUM, NULL, di)) +=09return 0; + } + + return n; +} + +/* + * handle:=090-based id of the device + * + * returns:=090 when OK, err otherwise + */ +int +ub_dev_open (int handle) +{ + struct device_info *di; + int err =3D 0; + + if (handle < 0 || handle >=3D UB_MAX_DEV) + return API_EINVAL; + + di =3D &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 >=3D UB_MAX_DEV) + return API_EINVAL; + + di =3D &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:=090/1 accordingly + */ +static int +dev_valid (int handle) +{ + if (handle < 0 || handle >=3D UB_MAX_DEV) + return 0; + + if (devices[handle].state !=3D 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, +=09 lbasize_t * rlen) +{ + struct device_info *di; + lbasize_t act_len; + int err =3D 0; + + if (!dev_stor_valid (handle)) + return API_ENODEV; + + di =3D &devices[handle]; + if (!syscall (API_DEV_READ, &err, di, buf, &len, &start, &act_len)) + return API_ESYSC; + + if (!err && rlen) + *rlen =3D act_len; + + return err; +} + +static int +dev_net_valid (int handle) +{ + if (!dev_valid (handle)) + return 0; + + if (devices[handle].type !=3D 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 =3D 0, act_len; + + if (!dev_net_valid (handle)) + return API_ENODEV; + + di =3D &devices[handle]; + if (!syscall (API_DEV_READ, &err, di, buf, &len, &act_len)) + return API_ESYSC; + + if (!err && rlen) + *rlen =3D act_len; + + return (err); +} + +int +ub_dev_send (int handle, void *buf, int len) +{ + struct device_info *di; + int err =3D 0; + + if (!dev_net_valid (handle)) + return API_ENODEV; + + di =3D &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 =3D NULL; + + /* + * It's OK to pass only the name piece as last (and not the whole + * 'name=3Dval' 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 =3D 0, str =3D env; *str !=3D '=3D' && *str !=3D '\0';) + env_name[i++] =3D *str++; + + env_name[i] =3D '\0'; + + return env_name; +} + +/**************************************** + * + * display + * + ****************************************/ + +int +ub_display_get_info (int type, struct display_info *di) +{ + int err =3D 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 =3D 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); +} =3D=3D=3D added file 'grub-core/kern/uboot/hw.c' --- grub-core/kern/uboot/hw.c=091970-01-01 00:00:00 +0000 +++ grub-core/kern/uboot/hw.c=092012-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 =3D ub_get_sys_info (); + + grub_mm_init_region ((void *) (grub_modules_get_end () +=09=09=09=09 + GRUB_KERNEL_MACHINE_STACK_SIZE), +=09=09 HEAP_MIN_SIZE); + + if (si && (si->mr_no !=3D 0)) + { + int i; + start_of_ram =3D GRUB_UINT_MAX; + + for (i =3D 0; i < si->mr_no; i++) +=09if ((si->mr[i].flags & MR_ATTR_MASK) =3D=3D MR_ATTR_DRAM) +=09 if (si->mr[i].start < start_of_ram) +=09 start_of_ram =3D si->mr[i].start; + } +} + +/* + * grub_uboot_probe_hardware(): + * =20 + */ +grub_err_t +grub_uboot_probe_hardware (void) +{ + int devcount, i; + + devcount =3D ub_dev_enum (); + grub_dprintf ("init", "%d devices found\n", devcount); + + for (i =3D 0; i < devcount; i++) + { + struct device_info *devinfo =3D ub_dev_get (i); + + grub_dprintf ("init", "device handle: %d\n", i); + grub_dprintf ("init", " cookie\t=3D 0x%08x\n", +=09=09 (grub_uint32_t) devinfo->cookie); + + if (devinfo->type & DEV_TYP_STOR) +=09{ +=09 grub_dprintf ("init", " type\t\t=3D DISK\n"); +=09 grub_ubootdisk_register (devinfo, i); +=09} + else if (devinfo->type & DEV_TYP_NET) +=09{ +=09 grub_dprintf ("init", " type\t\t=3D NET (not supported yet)\n"); +=09} + else +=09{ +=09 grub_dprintf ("init", "%s: unknown device type", __FUNCTION__); +=09} + } + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_machine_mmap_iterate (grub_memory_hook_t hook) +{ + int i; + struct sys_info *si =3D ub_get_sys_info (); + + if (!si || (si->mr_no < 1)) + return GRUB_ERR_BUG; + + /* Iterate and call `hook'. */ + for (i =3D 0; i < si->mr_no; i++) + if ((si->mr[i].flags & MR_ATTR_MASK) =3D=3D MR_ATTR_DRAM) + hook (si->mr[i].start, si->mr[i].size, GRUB_MEMORY_AVAILABLE); + + return GRUB_ERR_NONE; +} =3D=3D=3D added file 'grub-core/kern/uboot/init.c' --- grub-core/kern/uboot/init.c=091970-01-01 00:00:00 +0000 +++ grub-core/kern/uboot/init.c=092012-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 =3D 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_si= ze, + * whichever greater. + */ + end =3D (grub_addr_t) __bss_start + grub_total_module_size; + if (end < (grub_addr_t) _end) + end =3D (grub_addr_t) _end; + grub_modbase =3D 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"= , +=09=09(grub_addr_t) __bss_start, +=09=09(grub_addr_t) __bss_start + grub_total_module_size, +=09=09(grub_addr_t) _end); + grub_dprintf ("init", "grub_modbase: %p\n", (void *) grub_modbase); + grub_dprintf ("init", "grub_modules_get_end(): %p\n", +=09=09(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 =3D 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 parenthes= es) + * 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 =3D ub_env_get ("grub_bootdev"); + if (tmp) + { + *device =3D grub_malloc (grub_strlen (tmp) + 1); + if (*device =3D=3D NULL) +=09return; + grub_strncpy (*device, tmp, grub_strlen (tmp) + 1); + } + else + *device =3D NULL; + + tmp =3D ub_env_get ("grub_bootpath"); + if (tmp) + { + *path =3D grub_malloc (grub_strlen (tmp) + 1); + if (*path =3D=3D NULL) +=09return; + grub_strncpy (*path, tmp, grub_strlen (tmp) + 1); + } + else + *path =3D NULL; +} + +void +grub_uboot_fini (void) +{ + grub_ubootdisk_fini (); + grub_console_fini (); +} =3D=3D=3D added file 'grub-core/kern/uboot/uboot.c' --- grub-core/kern/uboot/uboot.c=091970-01-01 00:00:00 +0000 +++ grub-core/kern/uboot/uboot.c=092012-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); +} =3D=3D=3D added directory 'grub-core/lib/arm' =3D=3D=3D added file 'grub-core/lib/arm/libgcc.S' --- grub-core/lib/arm/libgcc.S=091970-01-01 00:00:00 +0000 +++ grub-core/lib/arm/libgcc.S=092012-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 + +=09.file=09"libgcc.S" +=09.syntax=09unified +#if !defined (__thumb2__) +=09.arm +#define ARM(x...)=09x +#define THUMB(x...) +#else +=09.thumb +#define THUMB(x...)=09x +#define ARM(x...) +#endif + +=09 +#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 + +=09.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 +=09bx=09lr + +12: ARM_DIV2_ORDER r1, r2 + + mov r0, r0, lsr r2 +=09bx=09lr + +FUNCTION(__aeabi_idiv) + cmp r1, #0 + eor ip, r0, r1 @ save the sign of the res= ult. + 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 +=09bx=09lr + +10: teq ip, r0 @ same sign ? + rsbmi r0, r0, #0 +=09bx=09lr + +11: movlo r0, #0 + moveq r0, ip, asr #31 + orreq r0, r0, #1 +=09bx=09lr + +12: ARM_DIV2_ORDER r1, r2 + + cmp ip, #0 + mov r0, r3, lsr r2 + rsbmi r0, r0, #0 +=09bx=09lr + +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 +=09bx=09lr + +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 +=09bx=09lr + +@ (Don't) handle division by 0 +FUNCTION(Ldiv0) +=09push=09{r4, lr} + mov r0, #0 @ About as wrong as it could be. +=09pop=09{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 +=09bx=09lr + +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 +=09bx=09lr + +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 +=09bx=09lr + + +/* + * Simple cache maintenance functions + */ + +@ r0 - *beg (inclusive) +@ r1 - *end (exclusive)=09 +clean_dcache_range: +=09@DCCMVAU +1:=09cmp=09r0, r1 +=09bge=092f +=09mcr=09p15, 0, r0, c7, c11, 1 +=09add=09r0, r0, #32 @ assume 32-byte cache line +2:=09dsb +=09bx=09lr + +@ r0 - *beg (inclusive) +@ r1 - *end (exclusive)=09 +invalidate_icache_range: +=09@ICIMVAU +1:=09cmp=09r0, r1 +=09bge=092f +=09mcr=09p15, 0, r0, c7, c5, 1 +=09@BPIMVA +=09mcr=09p15, 0, r0, c7,=09c5, 7 +=09add=09r0, r0, #32 @ assume 32-byte cache line +=09b=091b +=09dsb +2:=09isb +=09bx=09lr +=09 +@void __clear_cache(char *beg, char *end); +FUNCTION(__clear_cache) +=09push=09{r4-r6, lr} +=09mov=09r4, r0 +=09mov=09r5, r1 +=09bl=09clean_dcache_range +=09mov=09r0, r4 +=09mov=09r1, r5 +=09bl=09invalidate_icache_range +=09pop=09{r4-r6, pc} + +@void grub_arch_sync_caches (void *address, grub_size_t len) +FUNCTION(grub_arch_sync_caches) +=09add=09r1, r0, r1 +=09b=09__clear_cache + +=09.end =3D=3D=3D added file 'grub-core/lib/arm/setjmp.S' --- grub-core/lib/arm/setjmp.S=091970-01-01 00:00:00 +0000 +++ grub-core/lib/arm/setjmp.S=092012-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 + +=09.file=09"setjmp.S" +=09.syntax=09unified +#if !defined (__thumb2__) +=09.arm +#define ARM(x...)=09x +#define THUMB(x...) +#else +=09.thumb +#define THUMB(x...)=09x +#define ARM(x...) +#endif + +GRUB_MOD_LICENSE "GPLv3+" + +=09.text + +/* + * int grub_setjmp (grub_jmp_buf env) + */ +FUNCTION(grub_setjmp) + THUMB(=09mov=09ip, sp=09=09=09) + THUMB(=09stm=09r0, { r4-r11, ip, lr }=09) + ARM(=09stm=09r0, { r4-r11, sp, lr }=09) +=09mov=09r0, #0 +=09bx=09lr + +/* + * int grub_longjmp (grub_jmp_buf env, int val) + */ +FUNCTION(grub_longjmp) + THUMB(=09ldm=09r0, { r4-r11, ip, lr }=09) + THUMB(=09mov=09sp, ip=09=09=09) + ARM(=09ldm=09r0, { r4-r11, sp, lr }=09) +=09movs=09r0, r1 +=09moveq=09r0, #1 +=09bx=09lr =3D=3D=3D modified file 'grub-core/lib/setjmp.S' --- grub-core/lib/setjmp.S=092012-01-18 13:04:52 +0000 +++ grub-core/lib/setjmp.S=092012-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 =3D=3D=3D added directory 'grub-core/lib/uboot' =3D=3D=3D added file 'grub-core/lib/uboot/datetime.c' --- grub-core/lib/uboot/datetime.c=091970-01-01 00:00:00 +0000 +++ grub-core/lib/uboot/datetime.c=092012-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, +=09=09 "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, +=09=09 "can\'t set datetime using U-Boot"); +} =3D=3D=3D added file 'grub-core/lib/uboot/halt.c' --- grub-core/lib/uboot/halt.c=091970-01-01 00:00:00 +0000 +++ grub-core/lib/uboot/halt.c=092012-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); +} =3D=3D=3D added file 'grub-core/lib/uboot/reboot.c' --- grub-core/lib/uboot/reboot.c=091970-01-01 00:00:00 +0000 +++ grub-core/lib/uboot/reboot.c=092012-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); +} =3D=3D=3D added directory 'grub-core/loader/arm' =3D=3D=3D added directory 'grub-core/loader/arm/uboot' =3D=3D=3D added file 'grub-core/loader/arm/uboot/linux.c' --- grub-core/loader/arm/uboot/linux.c=091970-01-01 00:00:00 +0000 +++ grub-core/loader/arm/uboot/linux.c=092012-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 =3D fdt_totalsize ((void *) boot_data) + FDT_ADDITIONAL_ENTRIES= _SIZE; + tmp_fdt =3D 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 =3D fdt_subnode_offset (tmp_fdt, 0, "chosen"); + if (node < 0) + { + grub_printf ("No 'chosen' node in FDT - creating.\n"); + node =3D fdt_add_subnode (tmp_fdt, 0, "chosen"); + if (node < 0) +=09goto failure; + } + + grub_printf ("linux_args: '%s'\n", linux_args); + + /* Generate and set command line */ + retval =3D fdt_setprop (tmp_fdt, node, "bootargs", linux_args, +=09=09=09grub_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 =3D cpu_to_fdt32 (initrd_start); + grub_uint32_t fdt_initrd_end =3D cpu_to_fdt32 (initrd_end); + + grub_dprintf ("loader", "Initrd @ 0x%08x-0x%08x\n", +=09=09 initrd_start, initrd_end); + + retval =3D fdt_setprop (tmp_fdt, node, "linux,initrd-start", +=09=09=09 &fdt_initrd_start, sizeof (fdt_initrd_start)); + if (retval) +=09goto failure; + retval =3D fdt_setprop (tmp_fdt, node, "linux,initrd-end", +=09=09=09 &fdt_initrd_end, sizeof (fdt_initrd_end)); + if (retval) +=09goto 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) +=09{ +=09 grub_printf ("Using firmware-supplied boot data @ 0x%08x\n", +=09=09 firmware_boot_data); +=09 boot_data =3D firmware_boot_data; +=09} + else +=09{ +=09 return GRUB_ERR_FILE_NOT_FOUND; +=09} + } + + grub_dprintf ("loader", "Boot data at: 0x%x\n", boot_data); + + if (fdt32_to_cpu (*(grub_uint32_t *) (boot_data)) =3D=3D FDT_MAGIC) + { + grub_dprintf ("loader", "FDT @ 0x%08x\n", (grub_addr_t) boot_data); + if (linux_prepare_fdt () !=3D GRUB_ERR_NONE) +=09{ +=09 grub_dprintf ("loader", "linux_prepare_fdt() failed\n"); +=09 return GRUB_ERR_FILE_NOT_FOUND; +=09} + } + + 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 =3D (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 =3D grub_file_open (filename); + if (!file) + return GRUB_ERR_FILE_NOT_FOUND; + + size =3D grub_file_size (file); + if (size =3D=3D 0) + return GRUB_ERR_FILE_READ_ERROR; + + linux_addr =3D LINUX_ADDRESS; + grub_dprintf ("loader", "Loading Linux to 0x%08x\n", +=09=09(grub_addr_t) linux_addr); + + if (grub_file_read (file, (void *) linux_addr, size) !=3D size) + { + grub_printf ("Kernel read failed!\n"); + return GRUB_ERR_FILE_READ_ERROR; + } + + if (*(grub_uint32_t *) (linux_addr + LINUX_ZIMAGE_OFFSET) + !=3D LINUX_ZIMAGE_MAGIC) + { + return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("invalid zImage")); + } + + linux_size =3D size; + + return GRUB_ERR_NONE; +} + +static grub_err_t +linux_unload (void) +{ + grub_dl_unref (my_mod); + + grub_free (linux_args); + linux_args =3D NULL; + + initrd_start =3D initrd_end =3D 0; + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), +=09=09int argc, char *argv[]) +{ + int size, retval; + grub_file_t file; + grub_dl_ref (my_mod); + + if (argc =3D=3D 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); + + file =3D grub_file_open (argv[0]); + if (!file) + goto fail; + + retval =3D linux_load (argv[0]); + grub_file_close (file); + if (retval !=3D GRUB_ERR_NONE) + goto fail; + + grub_loader_set (linux_boot, linux_unload, 1); + + size =3D grub_loader_cmdline_size (argc, argv); + linux_args =3D 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, +=09=09=09 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)), +=09=09 int argc, char *argv[]) +{ + grub_file_t file; + int size; + + if (argc =3D=3D 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); + + file =3D grub_file_open (argv[0]); + if (!file) + return grub_errno; + + size =3D grub_file_size (file); + if (size =3D=3D 0) + goto fail; + + initrd_start =3D LINUX_INITRD_ADDRESS; + grub_dprintf ("loader", "Loading initrd to 0x%08x\n", +=09=09(grub_addr_t) initrd_start); + + if (grub_file_read (file, (void *) initrd_start, size) !=3D size) + goto fail; + + initrd_end =3D 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 =3D NULL; + + dtb =3D grub_file_open (path); + if (!dtb) + return NULL; + + size =3D grub_file_size (dtb); + if (size =3D=3D 0) + goto out; + + fdt =3D grub_malloc (size); + if (!fdt) + goto out; + + if (grub_file_read (dtb, fdt, size) !=3D size) + { + grub_free (fdt); + fdt =3D NULL; + goto out; + } + + if (fdt_check_header (fdt) !=3D 0) + { + grub_free (fdt); + fdt =3D NULL; + } + +out: + grub_file_close (dtb); + + return fdt; +} + +static grub_err_t +grub_cmd_devicetree (grub_command_t cmd __attribute__ ((unused)), +=09=09 int argc, char *argv[]) +{ + void *blob; + + if (argc !=3D 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); + + blob =3D load_dtb (argv[0]); + if (!blob) + return GRUB_ERR_FILE_NOT_FOUND; + + boot_data =3D LINUX_FDT_ADDRESS; + grub_dprintf ("loader", "Loading device tree to 0x%08x\n", +=09=09(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 =3D grub_register_command ("linux", grub_cmd_linux, +=09=09=09=09 0, N_("Load Linux.")); + cmd_initrd =3D grub_register_command ("initrd", grub_cmd_initrd, +=09=09=09=09 0, N_("Load initrd.")); + cmd_devicetree =3D grub_register_command ("devicetree", grub_cmd_devicet= ree, +=09=09=09=09=09 0, N_("Load DTB file.")); + my_mod =3D mod; + firmware_boot_data =3D uboot_get_boot_data (); + + boot_data =3D (grub_addr_t) NULL; + machine_type =3D uboot_get_machine_type (); +} + +GRUB_MOD_FINI (linux) +{ + grub_unregister_command (cmd_linux); + grub_unregister_command (cmd_initrd); + grub_unregister_command (cmd_devicetree); +} =3D=3D=3D modified file 'grub-core/term/terminfo.c' --- grub-core/term/terminfo.c=092012-09-18 09:52:19 +0000 +++ grub-core/term/terminfo.c=092012-10-22 18:29:17 +0000 @@ -746,7 +746,9 @@ =20 static grub_extcmd_t cmd; =20 -#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) =3D=3D=3D added directory 'grub-core/term/uboot' =3D=3D=3D added file 'grub-core/term/uboot/console.c' --- grub-core/term/uboot/console.c=091970-01-01 00:00:00 +0000 +++ grub-core/term/uboot/console.c=092012-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 +=09=09=09 __attribute__ ((unused)), int on +=09=09=09 __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 =3D 80; + if (!uboot_console_terminfo_output.height) + uboot_console_terminfo_output.height =3D 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 =3D { + .readkey =3D readkey +}; + +struct grub_terminfo_output_state uboot_console_terminfo_output =3D { + .put =3D put, + .width =3D 80, + .height =3D 24 +}; + +static struct grub_term_input uboot_console_term_input =3D { + .name =3D "console", + .init =3D uboot_console_init_input, + .getkey =3D grub_terminfo_getkey, + .data =3D &uboot_console_terminfo_input +}; + +static struct grub_term_output uboot_console_term_output =3D { + .name =3D "console", + .init =3D uboot_console_init_output, + .putchar =3D grub_terminfo_putchar, + .getwh =3D grub_terminfo_getwh, + .getxy =3D grub_terminfo_getxy, + .gotoxy =3D grub_terminfo_gotoxy, + .cls =3D grub_terminfo_cls, + .setcolorstate =3D grub_terminfo_setcolorstate, + .setcursor =3D uboot_console_setcursor, + .flags =3D GRUB_TERM_CODE_TYPE_ASCII, + .data =3D &uboot_console_terminfo_output, + .normal_color =3D GRUB_TERM_DEFAULT_NORMAL_COLOR, + .highlight_color =3D 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. + * =20 + */ +void +grub_console_init_lately (void) +{ + const char *type; + + /* See if explicitly set by U-Boot environment */ + type =3D ub_env_get ("grub_term"); + if (!type) + type =3D "vt100"; + + grub_terminfo_init (); + grub_terminfo_output_register (&uboot_console_term_output, type); +} + +void +grub_console_fini (void) +{ +} =3D=3D=3D added directory 'include/grub/arm' =3D=3D=3D added file 'include/grub/arm/linux.h' --- include/grub/arm/linux.h=091970-01-01 00:00:00 +0000 +++ include/grub/arm/linux.h=092012-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=090x300 + +typedef void (*kernel_entry_t) (int, unsigned long, void *); + +#endif /* ! GRUB_LINUX_CPU_HEADER */ =3D=3D=3D added file 'include/grub/arm/time.h' --- include/grub/arm/time.h=091970-01-01 00:00:00 +0000 +++ include/grub/arm/time.h=092012-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=091 + +static __inline void +grub_cpu_idle (void) +{ + /* FIXME: this can't work until we handle interrupts. */ +/* __asm__ __volatile__ ("wfi"); */ +} + +#endif /* ! KERNEL_CPU_TIME_HEADER */ =3D=3D=3D added file 'include/grub/arm/types.h' --- include/grub/arm/types.h=091970-01-01 00:00:00 +0000 +++ include/grub/arm/types.h=092012-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=091 + +/* The size of void *. */ +#define GRUB_TARGET_SIZEOF_VOID_P=094 + +/* The size of long. */ +#define GRUB_TARGET_SIZEOF_LONG=09=094 + +/* 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 */ =3D=3D=3D added directory 'include/grub/arm/uboot' =3D=3D=3D added file 'include/grub/arm/uboot/kernel.h' --- include/grub/arm/uboot/kernel.h=091970-01-01 00:00:00 +0000 +++ include/grub/arm/uboot/kernel.h=092012-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=091 + +#define GRUB_KERNEL_MACHINE_STACK_SIZE 0x40000 + +#ifndef ASM_FILE + +#include +#include + +#endif /* ! ASM_FILE */ + +#endif /* ! GRUB_KERNEL_MACHINE_HEADER */ =3D=3D=3D modified file 'include/grub/disk.h' --- include/grub/disk.h=092012-02-09 22:15:27 +0000 +++ include/grub/disk.h=092012-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, +}; =20 struct grub_disk; #ifdef GRUB_UTIL @@ -49,12 +50,12 @@ #endif =20 typedef enum - {=20 - 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; =20 /* Disk device. */ struct grub_disk_dev @@ -66,26 +67,25 @@ enum grub_disk_dev_id id; =20 /* Call HOOK with each device name, until HOOK returns non-zero. */ - int (*iterate) (int (*hook) (const char *name), -=09=09 grub_disk_pull_t pull); + int (*iterate) (int (*hook) (const char *name), grub_disk_pull_t pull); =20 /* 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); =20 /* Close the disk DISK. */ - void (*close) (struct grub_disk *disk); + void (*close) (struct grub_disk * disk); =20 /* 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, -=09=09 grub_size_t size, char *buf); + grub_err_t (*read) (struct grub_disk * disk, grub_disk_addr_t sector, +=09=09=09grub_size_t size, char *buf); =20 /* 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, -=09=09 grub_size_t size, const char *buf); + grub_err_t (*write) (struct grub_disk * disk, grub_disk_addr_t sector, +=09=09=09 grub_size_t size, const char *buf); =20 #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 =20 /* 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, -=09=09 unsigned offset, unsigned length); +=09=09=09=09 unsigned offset, unsigned length); =20 /* Device-specific data. */ void *data; @@ -155,8 +155,8 @@ /* This is called from the memory manager. */ void grub_disk_cache_invalidate_all (void); =20 -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; } =20 -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, -=09=09=09=09=09grub_disk_addr_t sector, -=09=09=09=09=09grub_off_t offset, -=09=09=09=09=09grub_size_t size, -=09=09=09=09=09void *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, =09=09=09=09=09 grub_disk_addr_t sector, =09=09=09=09=09 grub_off_t offset, -=09=09=09=09=09 grub_size_t size, -=09=09=09=09=09 const void *buf); +=09=09=09=09=09 grub_size_t size, void *buf); +grub_err_t EXPORT_FUNC (grub_disk_write) (grub_disk_t disk, +=09=09=09=09=09 grub_disk_addr_t sector, +=09=09=09=09=09 grub_off_t offset, +=09=09=09=09=09 grub_size_t size, const void *buf); =20 -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); =20 #if DISK_CACHE_STATS void -EXPORT_FUNC(grub_disk_cache_get_performance) (unsigned long *hits, unsigne= d long *misses); +EXPORT_FUNC (grub_disk_cache_get_performance) (unsigned long *hits, +=09=09=09=09=09 unsigned long *misses); #endif =20 -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); =20 #if defined (GRUB_UTIL) void grub_lvm_init (void); =3D=3D=3D modified file 'include/grub/elf.h' --- include/grub/elf.h=092012-06-18 19:09:57 +0000 +++ include/grub/elf.h=092012-10-22 18:29:17 +0000 @@ -145,6 +145,7 @@ #define ELFOSABI_TRU64=09=0910=09/* Compaq TRU64 UNIX. */ #define ELFOSABI_MODESTO=0911=09/* Novell Modesto. */ #define ELFOSABI_OPENBSD=0912=09/* OpenBSD. */ +#define ELFOSABI_ARM_AEABI=0964=09/* ARM EABI */ #define ELFOSABI_ARM=09=0997=09/* ARM */ #define ELFOSABI_STANDALONE=09255=09/* Standalone (embedded) application *= / =20 @@ -2005,15 +2006,18 @@ /* ARM specific declarations */ =20 /* 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=09=09/* 8-bit structure alignment is in us= e */ -#define EF_ARM_NEW_ABI 0x80 -#define EF_ARM_OLD_ABI 0x100 +#define EF_ARM_RELEXEC =090x01 +#define EF_ARM_HASENTRY =090x02 +#define EF_ARM_INTERWORK =090x04 +#define EF_ARM_APCS_26 =090x08 +#define EF_ARM_APCS_FLOAT =090x10 +#define EF_ARM_PIC =090x20 +#define EF_ARM_ALIGN8 =090x40 /* 8-bit structure alignment is in use = */ +#define EF_ARM_NEW_ABI =090x80 +#define EF_ARM_OLD_ABI =090x100 +#define EF_ARM_SOFT_FLOAT=090x200 +#define EF_ARM_VFP_FLOAT=090x400 +#define EF_ARM_MAVERICK_FLOAT=090x800 =20 /* 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=090x10 #define EF_ARM_EABIMASK=09=090XFF000000 =20 +/* Constants defined in AAELF. */ +#define EF_ARM_BE8=09 0x00800000 +#define EF_ARM_LE8=09 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 =20 /* Additional symbol types for Thumb */ -#define STT_ARM_TFUNC 0xd +#define STT_ARM_TFUNC=09 STT_LOPROC /* A Thumb function. */ +#define STT_ARM_16BIT=09 STT_HIPROC /* A Thumb label. */ =20 /* 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 =09=09=09=09=09 addressed by the static base */ +#define PF_ARM_PI=09 0x20000000 /* Position-independent segment. */ +#define PF_ARM_ABS=09 0x40000000 /* Absolute segment. */ + +/* Processor specific values for the Phdr p_type field. */ +#define PT_ARM_EXIDX=09=09(PT_LOPROC + 1)=09/* ARM unwind segment. */ + +/* Processor specific values for the Shdr sh_type field. */ +#define SHT_ARM_EXIDX=09=09(SHT_LOPROC + 1) /* ARM unwind section. */ +#define SHT_ARM_PREEMPTMAP=09(SHT_LOPROC + 2) /* Preemption details. */ +#define SHT_ARM_ATTRIBUTES=09(SHT_LOPROC + 3) /* ARM attributes section. = */ + =20 /* ARM relocs. */ #define R_ARM_NONE=09=090=09/* No reloc */ @@ -2050,7 +2073,7 @@ #define R_ARM_THM_ABS5=09=097 #define R_ARM_ABS8=09=098=09/* Direct 8 bit */ #define R_ARM_SBREL32=09=099 -#define R_ARM_THM_PC22=09=0910 +#define R_ARM_THM_CALL=09=0910 #define R_ARM_THM_PC8=09=0911 #define R_ARM_AMP_VCALL9=0912 #define R_ARM_SWI24=09=0913 @@ -2065,16 +2088,36 @@ #define R_ARM_GOTPC=09=0925=09/* 32 bit PC relative offset to GOT */ #define R_ARM_GOT32=09=0926=09/* 32 bit GOT entry */ #define R_ARM_PLT32=09=0927=09/* 32 bit PLT address */ +#define R_ARM_CALL=09=0928 +#define R_ARM_JUMP24=09=0929 +#define R_ARM_THM_JUMP24=0930 +#define R_ARM_BASE_ABS=09=0931 #define R_ARM_ALU_PCREL_7_0=0932 #define R_ARM_ALU_PCREL_15_8=0933 #define R_ARM_ALU_PCREL_23_15=0934 #define R_ARM_LDR_SBREL_11_0=0935 #define R_ARM_ALU_SBREL_19_12=0936 #define R_ARM_ALU_SBREL_27_20=0937 +#define R_ARM_TLS_GOTDESC=0990 +#define R_ARM_TLS_CALL=09=0991 +#define R_ARM_TLS_DESCSEQ=0992 +#define R_ARM_THM_TLS_CALL=0993 #define R_ARM_GNU_VTENTRY=09100 #define R_ARM_GNU_VTINHERIT=09101 #define R_ARM_THM_PC11=09=09102=09/* thumb unconditional branch */ #define R_ARM_THM_PC9=09=09103=09/* thumb conditional branch */ +#define R_ARM_TLS_GD32=09=09104=09/* PC-rel 32 bit for global dynamic +=09=09=09=09=09 thread local data */ +#define R_ARM_TLS_LDM32=09=09105=09/* PC-rel 32 bit for local dynamic +=09=09=09=09=09 thread local data */ +#define R_ARM_TLS_LDO32=09=09106=09/* 32 bit offset relative to TLS +=09=09=09=09=09 block */ +#define R_ARM_TLS_IE32=09=09107=09/* PC-rel 32 bit for GOT entry of +=09=09=09=09=09 static TLS block offset */ +#define R_ARM_TLS_LE32=09=09108=09/* 32 bit offset relative to static +=09=09=09=09=09 TLS block */ +#define=09R_ARM_THM_TLS_DESCSEQ=09129 +#define R_ARM_IRELATIVE=09=09160 #define R_ARM_RXPC25=09=09249 #define R_ARM_RSBREL32=09=09250 #define R_ARM_THM_RPC22=09=09251 =3D=3D=3D modified file 'include/grub/libgcc.h' --- include/grub/libgcc.h=092012-02-29 14:28:02 +0000 +++ include/grub/libgcc.h=092012-10-22 18:29:17 +0000 @@ -24,59 +24,59 @@ =20 /* 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 =20 -# ifdef HAVE___IA64_TRAMPOLINE +#ifdef HAVE___IA64_TRAMPOLINE void EXPORT_FUNC (__ia64_trampoline) (void); -# endif +#endif =20 #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 =3D=3D=3D modified file 'include/grub/offsets.h' --- include/grub/offsets.h=092012-01-29 22:20:02 +0000 +++ include/grub/offsets.h=092012-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 =20 #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 =20 +#define GRUB_KERNEL_ARM_UBOOT_MOD_ALIGN =090x1 +#define GRUB_KERNEL_ARM_UBOOT_TOTAL_MODULE_SIZE=090x4 +#define GRUB_KERNEL_ARM_UBOOT_LINK_ADDR=09=090x08000000 + /* 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. */ =3D=3D=3D modified file 'include/grub/symbol.h' --- include/grub/symbol.h=092012-05-28 15:49:18 +0000 +++ include/grub/symbol.h=092012-10-22 18:29:17 +0000 @@ -29,12 +29,16 @@ =20 #if HAVE_ASM_USCORE #ifdef ASM_FILE -# define EXT_C(sym)=09_ ## sym -#else -# define EXT_C(sym)=09"_" sym -#endif -#else -# define EXT_C(sym)=09sym +#ifndef (__arm__) +#define EXT_C(sym)=09_ ## sym +#else +#define EXT_C(sym)=09% ## sym +#endif +#else +#define EXT_C(sym)=09"_" sym +#endif +#else +#define EXT_C(sym)=09sym #endif =20 #if defined (__APPLE__) @@ -52,8 +56,8 @@ =20 /* Mark an exported symbol. */ #ifndef GRUB_SYMBOL_GENERATOR -# define EXPORT_FUNC(x)=09x -# define EXPORT_VAR(x)=09x +#define EXPORT_FUNC(x)=09x +#define EXPORT_VAR(x)=09x #endif /* ! GRUB_SYMBOL_GENERATOR */ =20 #endif /* ! GRUB_SYMBOL_HEADER */ =3D=3D=3D added directory 'include/grub/uboot' =3D=3D=3D added file 'include/grub/uboot/api_public.h' --- include/grub/uboot/api_public.h=091970-01-01 00:00:00 +0000 +++ include/grub/uboot/api_public.h=092012-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 PURP= OSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENT= IAL + * 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, STR= ICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY W= AY + * 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=09=091=09/* invalid argument(s)=09*/ +#define API_ENODEV=09=092=09/* no device=09=09*/ +#define API_ENOMEM=09=093=09/* no memory=09=09*/ +#define API_EBUSY=09=094=09/* busy, occupied etc.=09*/ +#define API_EIO=09=09=095=09/* I/O error=09=09*/ +#define API_ESYSC=09=096=09/* syscall error=09*/ + +typedef=09int (*scp_t)(int, int *, ...); + +typedef grub_uint16_t uint16_t; +typedef grub_uint32_t uint32_t; + +#define API_SIG_VERSION=091 +#define API_SIG_MAGIC=09"UBootAPI" +#define API_SIG_MAGLEN=098 + +struct api_signature { +=09char=09=09magic[API_SIG_MAGLEN];=09/* magic string */ +=09uint16_t=09version;=09=09/* API version */ +=09uint32_t=09checksum;=09=09/* checksum of this sig struct */ +=09scp_t=09=09syscall;=09=09/* entry point to the API */ +}; + +enum { +=09API_RSVD =3D 0, +=09API_GETC, +=09API_PUTC, +=09API_TSTC, +=09API_PUTS, +=09API_RESET, +=09API_GET_SYS_INFO, +=09API_UDELAY, +=09API_GET_TIMER, +=09API_DEV_ENUM, +=09API_DEV_OPEN, +=09API_DEV_CLOSE, +=09API_DEV_READ, +=09API_DEV_WRITE, +=09API_ENV_ENUM, +=09API_ENV_GET, +=09API_ENV_SET, +=09API_DISPLAY_GET_INFO, +=09API_DISPLAY_DRAW_BITMAP, +=09API_DISPLAY_CLEAR, +=09API_MAXCALL +}; + +#define MR_ATTR_FLASH=090x0001 +#define MR_ATTR_DRAM=090x0002 +#define MR_ATTR_SRAM=090x0003 +#define MR_ATTR_MASK=090x000f + +struct mem_region { +=09unsigned long=09start; +=09unsigned long=09size; +=09int=09=09flags; +}; + +struct sys_info { +=09unsigned long=09=09clk_bus; +=09unsigned long=09=09clk_cpu; +=09unsigned long=09=09bar; +=09struct mem_region=09*mr; +=09int=09=09=09mr_no;=09/* number of memory regions */ +}; + +#undef CONFIG_SYS_64BIT_LBA +#ifdef CONFIG_SYS_64BIT_LBA +typedef=09u_int64_t lbasize_t; +#else +typedef unsigned long lbasize_t; +#endif +typedef unsigned long lbastart_t; + +#define DEV_TYP_NONE=090x0000 +#define DEV_TYP_NET=090x0001 + +#define DEV_TYP_STOR=090x0002 +#define DT_STOR_IDE=090x0010 +#define DT_STOR_SCSI=090x0020 +#define DT_STOR_USB=090x0040 +#define DT_STOR_MMC=090x0080 +#define DT_STOR_SATA=090x0100 + +#define DEV_STA_CLOSED=090x0000=09=09/* invalid, closed */ +#define DEV_STA_OPEN=090x0001=09=09/* open i.e. active */ + +struct device_info { +=09int=09type; +=09void=09*cookie; + +=09union { +=09=09struct { +=09=09=09lbasize_t=09block_count;=09/* no of blocks */ +=09=09=09unsigned long=09block_size;=09/* size of one block */ +=09=09} storage; + +=09=09struct { +=09=09=09unsigned char=09hwaddr[6]; +=09=09} net; +=09} info; +#define di_stor info.storage +#define di_net info.net + +=09int=09state; +}; + +#define DISPLAY_TYPE_LCD=090x0001 +#define DISPLAY_TYPE_VIDEO=090x0002 + +struct display_info { +=09int type; +=09/* screen size in pixels */ +=09int pixel_width; +=09int pixel_height; +=09/* screen size in rows and columns of text */ +=09int screen_rows; +=09int screen_cols; +}; + +#endif /* _API_PUBLIC_H_ */ =3D=3D=3D added file 'include/grub/uboot/console.h' --- include/grub/uboot/console.h=091970-01-01 00:00:00 +0000 +++ include/grub/uboot/console.h=092012-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 */ =3D=3D=3D added file 'include/grub/uboot/disk.h' --- include/grub/uboot/disk.h=091970-01-01 00:00:00 +0000 +++ include/grub/uboot/disk.h=092012-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=091 + +#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 */ =3D=3D=3D added file 'include/grub/uboot/glue.h' --- include/grub/uboot/glue.h=091970-01-01 00:00:00 +0000 +++ include/grub/uboot/glue.h=092012-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=09=09(3 * 1024 * 1024)=09/* 3MB search range */ + +#define UB_MAX_MR=095=09/* max mem regions number */ +#define UB_MAX_DEV=096=09/* max devices number */ + +extern grub_uint32_t uboot_search_hint; + +int=09api_search_sig(struct api_signature **sig); + +/* + * The ub_ library calls are part of the application, not U-Boot code! Th= ey + * 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=09ub_getc(void); +int=09ub_tstc(void); +void=09ub_putc(char c); +void=09ub_puts(const char *s); + +/* system */ +void=09EXPORT_FUNC(ub_reset) (void); +struct sys_info *=09ub_get_sys_info(void); + +/* time */ +void=09=09ub_udelay(unsigned long); +unsigned long=09ub_get_timer(unsigned long); + +/* env vars */ +char *=09=09ub_env_get(const char *name); +void=09=09ub_env_set(const char *name, char *value); +const char *=09ub_env_enum(const char *last); + +/* devices */ +int=09=09=09ub_dev_enum(void); +int=09EXPORT_FUNC(ub_dev_open)(int handle); +int=09EXPORT_FUNC(ub_dev_close)(int handle); +int=09=09=09ub_dev_read(int handle, void *buf, lbasize_t len, +=09=09=09=09lbastart_t start, lbasize_t *rlen); +int=09EXPORT_FUNC(ub_dev_send)(int handle, void *buf, int len); +int=09EXPORT_FUNC(ub_dev_recv)(int handle, void *buf, int len, int *rlen); +struct device_info *=09ub_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_ */ =3D=3D=3D added file 'include/grub/uboot/uboot.h' --- include/grub/uboot/uboot.h=091970-01-01 00:00:00 +0000 +++ include/grub/uboot/uboot.h=092012-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=091 + +#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 */ =3D=3D=3D modified file 'util/grub-install.in' --- util/grub-install.in=092012-09-24 17:50:35 +0000 +++ util/grub-install.in=092012-10-22 18:29:17 +0000 @@ -321,6 +321,8 @@ =09=09 target=3Di386-pc =09=09fi =09=09;; +=09 x"arm"*) +=09=09target=3D"arm-uboot";; =09 *) =09=09gettext "Unable to determine your platform. Use --target." ; =09=09echo=09;; @@ -340,7 +342,7 @@ if [ x$disk_module =3D xunspecified ]; then =09disk_module=3Dbiosdisk fi -elif [ "${grub_modinfo_platform}" =3D "ieee1275" ] || [ "${grub_modinfo_pl= atform}" =3D "efi" ] || [ "${grub_modinfo_platform}" =3D "arc" ] ; then +elif [ "${grub_modinfo_platform}" =3D "ieee1275" ] || [ "${grub_modinfo_pl= atform}" =3D "efi" ] || [ "${grub_modinfo_platform}" =3D "arc" ] || [ "${gr= ub_modinfo_platform}" =3D "uboot" ] ; then disk_module=3D else disk_module=3Dnative =3D=3D=3D modified file 'util/grub-mkimage.c' --- util/grub-mkimage.c=092012-06-26 01:38:10 +0000 +++ util/grub-mkimage.c=092012-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 =3D GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN, .default_compression =3D COMPRESSION_NONE }, + { + .dirname =3D "arm-uboot", + .names =3D { "arm-uboot", NULL }, + .voidp_sizeof =3D 4, + .bigendian =3D 0, + .id =3D IMAGE_UBOOT,=20 + .flags =3D PLATFORM_FLAGS_NONE, + .total_module_size =3D GRUB_KERNEL_ARM_UBOOT_TOTAL_MODULE_SIZE, + .decompressor_compressed_size =3D TARGET_NO_FIELD, + .decompressor_uncompressed_size =3D TARGET_NO_FIELD, + .decompressor_uncompressed_addr =3D TARGET_NO_FIELD, + .section_align =3D 1, + .vaddr_offset =3D 0, + .link_addr =3D GRUB_KERNEL_ARM_UBOOT_LINK_ADDR, + .elf_target =3D EM_ARM, + .mod_gap =3D GRUB_KERNEL_ARM_UBOOT_MOD_GAP, + .mod_align =3D GRUB_KERNEL_ARM_UBOOT_MOD_ALIGN, + .link_align =3D 4 + }, }; =20 #define grub_target_to_host32(x) (grub_target_to_host32_real (image_target= , (x))) @@ -1626,12 +1645,18 @@ =09core_size =3D program_size + header_size + footer_size; } break; + case IMAGE_UBOOT: + /* Raw image, no header, added below */ + break; } =20 grub_util_write_image (core_img, core_size, out, outname); free (core_img); free (kernel_path); =20 + fflush (out); + fsync (fileno (out)); + while (path_list) { next =3D path_list->next; @@ -1639,6 +1664,41 @@ free (path_list); path_list =3D next; } + + /* Add U-Boot header using mkimage command */ + if (image_target->id =3D=3D IMAGE_UBOOT) + { + char cmdstr[1024]; + const char *arch; + int retval; + =20 + if (image_target->elf_target =3D=3D EM_ARM) +=09{ +=09 arch =3D "ARM"; +=09} + else +=09{ +=09 fprintf(stderr, "%s\n", _("Unsupported U-Boot architecture.")); +=09 return; +=09} + + retval =3D snprintf(cmdstr, sizeof(cmdstr), +=09=09=09"mkimage -T kernel -A %s -O Linux -a 0x%08x " \ +=09=09=09"-e 0x%08x -C none -d %s %s.ubt", +=09=09=09arch, (grub_uint32_t)GRUB_KERNEL_ARM_UBOOT_LINK_ADDR, +=09=09=09(grub_uint32_t)GRUB_KERNEL_ARM_UBOOT_LINK_ADDR, +=09=09=09outname, outname); + + if (retval >=3D sizeof(cmdstr)) +=09{ +=09 fprintf(stderr, "%s\n", _("mkimage command line truncated.")); +=09 return; +=09} + + retval =3D system(cmdstr); + if (retval !=3D 0) +=09fprintf(stderr, "%s\n", _("mkimage command failed.")); + } } =20 =0C @@ -1862,7 +1922,6 @@ if (! fp) =09grub_util_error (_("cannot open `%s': %s"), arguments.output, =09=09=09 strerror (errno)); - free (arguments.output); } =20 if (!arguments.dir) @@ -1882,12 +1941,13 @@ =09=09 arguments.modules, arguments.memdisk, arguments.config, =09=09 arguments.image_target, arguments.note, arguments.comp); =20 - fflush (fp); - fsync (fileno (fp)); fclose (fp); =20 if (arguments.dir) free (arguments.dir); =20 + if (arguments.output) + free (arguments.output); + return 0; } --------------000109090103020803060404--