* [PATCH 3/7] Initial support for U-Boot platforms
@ 2013-03-24 17:01 Leif Lindholm
2013-03-30 16:20 ` Francesco Lavra
2013-04-01 2:08 ` Vladimir 'φ-coder/phcoder' Serbinenko
0 siblings, 2 replies; 12+ messages in thread
From: Leif Lindholm @ 2013-03-24 17:01 UTC (permalink / raw)
To: grub-devel
[-- Attachment #1: Type: text/plain, Size: 1 bytes --]
[-- Attachment #2: 0003-uboot-support.patch --]
[-- Type: application/octet-stream, Size: 47329 bytes --]
=== modified file 'grub-core/Makefile.core.def'
--- grub-core/Makefile.core.def 2013-03-24 12:58:13 +0000
+++ grub-core/Makefile.core.def 2013-03-24 12:58:23 +0000
@@ -114,6 +114,12 @@
ieee1275 = term/ieee1275/console.c;
ieee1275 = kern/ieee1275/init.c;
+ uboot = disk/uboot/ubootdisk.c;
+ uboot = kern/uboot/uboot.c;
+ uboot = kern/uboot/init.c;
+ uboot = kern/uboot/hw.c;
+ uboot = term/uboot/console.c;
+
terminfoinkernel = term/terminfo.c;
terminfoinkernel = term/tparm.c;
terminfoinkernel = commands/extcmd.c;
@@ -698,6 +704,7 @@
efi = lib/efi/halt.c;
ieee1275 = lib/ieee1275/halt.c;
emu = lib/emu/halt.c;
+ uboot = lib/uboot/halt.c;
};
module = {
@@ -711,6 +718,7 @@
mips_arc = lib/mips/arc/reboot.c;
mips_loongson = lib/mips/loongson/reboot.c;
mips_qemu_mips = lib/mips/qemu_mips/reboot.c;
+ uboot = lib/uboot/reboot.c;
common = commands/reboot.c;
};
@@ -1363,6 +1371,7 @@
name = datetime;
cmos = lib/cmos_datetime.c;
efi = lib/efi/datetime.c;
+ uboot = lib/uboot/datetime.c;
sparc64_ieee1275 = lib/ieee1275/datetime.c;
powerpc_ieee1275 = lib/ieee1275/datetime.c;
sparc64_ieee1275 = lib/ieee1275/cmos.c;
=== added directory 'grub-core/disk/uboot'
=== added file 'grub-core/disk/uboot/ubootdisk.c'
--- grub-core/disk/uboot/ubootdisk.c 1970-01-01 00:00:00 +0000
+++ grub-core/disk/uboot/ubootdisk.c 2013-03-24 12:58:23 +0000
@@ -0,0 +1,346 @@
+/* ubootdisk.c - disk subsystem support for U-Boot platforms */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2013 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/disk.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/partition.h>
+#include <grub/term.h>
+#include <grub/types.h>
+#include <grub/uboot/disk.h>
+#include <grub/uboot/uboot.h>
+
+static struct ubootdisk_data *fd_devices;
+static struct ubootdisk_data *hd_devices;
+static struct ubootdisk_data *cd_devices;
+
+/*
+ * grub_ubootdisk_register():
+ * Called for each disk device enumerated as part of U-Boot initialization
+ * code.
+ */
+grub_err_t
+grub_ubootdisk_register (struct device_info *newdev, int handle)
+{
+ struct ubootdisk_data *d;
+ enum disktype type;
+
+#define STOR_TYPE(x) ((x) & 0x0ff0)
+ switch (STOR_TYPE (newdev->type))
+ {
+ case DT_STOR_IDE:
+ case DT_STOR_SATA:
+ /* hd */
+ type = hd;
+ break;
+ case DT_STOR_MMC:
+ case DT_STOR_USB:
+ /* fd */
+ type = fd;
+ break;
+ default:
+ return GRUB_ERR_BAD_DEVICE;
+ break;
+ }
+
+ d = (struct ubootdisk_data *) grub_malloc (sizeof (struct ubootdisk_data));
+ if (!d)
+ return GRUB_ERR_OUT_OF_MEMORY;
+ d->handle = handle;
+ d->cookie = newdev->cookie;
+ d->opencount = 0;
+
+ switch (type)
+ {
+ case cd:
+ grub_dprintf ("ubootdisk", "registering cd device\n");
+ d->next = cd_devices;
+ cd_devices = d;
+
+ break;
+ case fd:
+ grub_dprintf ("ubootdisk", "registering fd device\n");
+ d->next = fd_devices;
+ fd_devices = d;
+
+ break;
+ case hd:
+ grub_dprintf ("ubootdisk", "registering hd device\n");
+ d->next = hd_devices;
+ hd_devices = d;
+
+ break;
+ default:
+ grub_free (d);
+ return GRUB_ERR_BAD_DEVICE;
+ }
+
+ return 0;
+}
+
+/*
+ * uboot_disk_iterate():
+ * Itarator over enumerated disk devices.
+ */
+static int
+uboot_disk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
+ grub_disk_pull_t pull)
+{
+ struct ubootdisk_data *d;
+ char buf[16];
+ int count;
+
+ switch (pull)
+ {
+ case GRUB_DISK_PULL_NONE:
+ /* "hd" - built-in mass-storage */
+ for (d = hd_devices, count = 0; d; d = d->next, count++)
+ {
+ grub_snprintf (buf, sizeof (buf) - 1, "hd%d", count);
+ grub_dprintf ("ubootdisk", "iterating %s\n", buf);
+ if (hook (buf, hook_data))
+ return 1;
+ }
+ break;
+ case GRUB_DISK_PULL_REMOVABLE:
+ /* "floppy" - removable mass storage */
+ for (d = fd_devices, count = 0; d; d = d->next, count++)
+ {
+ grub_snprintf (buf, sizeof (buf) - 1, "fd%d", count);
+ grub_dprintf ("ubootdisk", "iterating %s\n", buf);
+ if (hook (buf, hook_data))
+ return 1;
+ }
+
+ /* "cdrom" - removeable read-only storage */
+ for (d = cd_devices, count = 0; d; d = d->next, count++)
+ {
+ grub_snprintf (buf, sizeof (buf) - 1, "cd%d", count);
+ grub_dprintf ("ubootdisk", "iterating %s\n", buf);
+ if (hook (buf, hook_data))
+ return 1;
+ }
+ break;
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+/* Helper function for uboot_disk_open. */
+static struct ubootdisk_data *
+get_device (struct ubootdisk_data *devices, int num)
+{
+ struct ubootdisk_data *d;
+
+ for (d = devices; d && num; d = d->next, num--)
+ ;
+
+ if (num == 0)
+ return d;
+
+ return NULL;
+}
+
+/*
+ * uboot_disk_open():
+ * Opens a disk device already enumerated.
+ */
+static grub_err_t
+uboot_disk_open (const char *name, struct grub_disk *disk)
+{
+ struct ubootdisk_data *d;
+ struct device_info *devinfo;
+ int num;
+ int retval;
+
+ grub_dprintf ("ubootdisk", "Opening '%s'\n", name);
+
+ num = grub_strtoul (name + 2, 0, 10);
+ if (grub_errno != GRUB_ERR_NONE)
+ {
+ grub_dprintf ("ubootdisk", "Opening '%s' failed, invalid number\n",
+ name);
+ goto fail;
+ }
+
+ if (name[1] != 'd')
+ {
+ grub_dprintf ("ubootdisk", "Opening '%s' failed, invalid name\n", name);
+ goto fail;
+ }
+
+ switch (name[0])
+ {
+ case 'f':
+ d = get_device (fd_devices, num);
+ break;
+ case 'c':
+ d = get_device (cd_devices, num);
+ break;
+ case 'h':
+ d = get_device (hd_devices, num);
+ break;
+ default:
+ goto fail;
+ }
+
+ if (!d)
+ goto fail;
+
+ /*
+ * Subsystems may call open on the same device recursively - but U-Boot
+ * does not deal with this. So simply keep track of number of calls and
+ * return success if already open.
+ */
+ if (d->opencount > 0)
+ {
+ grub_dprintf ("ubootdisk", "(%s) already open\n", disk->name);
+ d->opencount++;
+ retval = 0;
+ }
+ else
+ {
+ retval = uboot_dev_open (d->handle);
+ if (retval != 0)
+ goto fail;
+ d->opencount = 1;
+ }
+
+ grub_dprintf ("ubootdisk", "cookie: 0x%08x\n", (grub_addr_t) d->cookie);
+ disk->id = (grub_addr_t) d->cookie;
+
+ /* Device has previously been enumerated, so this should never fail */
+ if ((devinfo = uboot_dev_get (d->handle)) == NULL)
+ goto fail;
+
+ d->block_size = devinfo->di_stor.block_size;
+ if (d->block_size == 0)
+ {
+ grub_printf ("%s: no block size!\n", __FUNCTION__);
+ return GRUB_ERR_IO;
+ }
+
+ for (disk->log_sector_size = 0;
+ (1U << disk->log_sector_size) < d->block_size;
+ disk->log_sector_size++);
+
+ grub_dprintf ("ubootdisk", "(%s) blocksize=%d, log_sector_size=%d\n",
+ disk->name, d->block_size, disk->log_sector_size);
+
+ disk->total_sectors = GRUB_DISK_SIZE_UNKNOWN;
+ disk->data = d;
+
+ return GRUB_ERR_NONE;
+
+fail:
+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such device");
+}
+
+static void
+uboot_disk_close (struct grub_disk *disk)
+{
+ struct ubootdisk_data *d;
+ int retval;
+
+ d = disk->data;
+
+ /*
+ * In mirror of open function, keep track of number of calls to close and
+ * send on to U-Boot only when opencount would decrease to 0.
+ */
+ if (d->opencount > 1)
+ {
+ grub_dprintf ("ubootdisk", "Closed (%s)\n", disk->name);
+
+ d->opencount--;
+ }
+ else if (d->opencount == 1)
+ {
+ retval = uboot_dev_close (d->handle);
+ d->opencount--;
+ grub_dprintf ("ubootdisk", "closed %s (%d)\n", disk->name, retval);
+ }
+ else
+ {
+ grub_dprintf ("ubootdisk", "device %s not open!\n", disk->name);
+ }
+}
+
+/*
+ * uboot_disk_read():
+ * Called from within disk subsystem to read a sequence of blocks into the
+ * disk cache. Maps directly on top of U-Boot API, only wrap in some error
+ * handling.
+ */
+static grub_err_t
+uboot_disk_read (struct grub_disk *disk,
+ grub_disk_addr_t offset, grub_size_t numblocks, char *buf)
+{
+ struct ubootdisk_data *d;
+ lbasize_t real_size;
+ int retval;
+
+ d = disk->data;
+
+ retval = uboot_dev_read (d->handle, buf, numblocks, offset, &real_size);
+ grub_dprintf ("ubootdisk",
+ "retval=%d, numblocks=%d, real_size=%llu, sector=%llu\n",
+ retval, numblocks, (grub_uint64_t) real_size,
+ (grub_uint64_t) offset);
+ if (retval != 0)
+ return grub_error (GRUB_ERR_IO, "U-Boot disk read error");
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+uboot_disk_write (struct grub_disk *disk __attribute__ ((unused)),
+ grub_disk_addr_t sector __attribute__ ((unused)),
+ grub_size_t size __attribute__ ((unused)),
+ const char *buf __attribute__ ((unused)))
+{
+ grub_dprintf ("ubootdisk", "attempt to write\n");
+ return GRUB_ERR_NOT_IMPLEMENTED_YET;
+}
+
+static struct grub_disk_dev grub_ubootdisk_dev = {
+ .name = "ubootdisk",
+ .id = GRUB_DISK_DEVICE_UBOOTDISK_ID,
+ .iterate = uboot_disk_iterate,
+ .open = uboot_disk_open,
+ .close = uboot_disk_close,
+ .read = uboot_disk_read,
+ .write = uboot_disk_write,
+ .next = 0
+};
+
+void
+grub_ubootdisk_init (void)
+{
+ grub_disk_dev_register (&grub_ubootdisk_dev);
+}
+
+void
+grub_ubootdisk_fini (void)
+{
+ grub_disk_dev_unregister (&grub_ubootdisk_dev);
+}
=== added directory 'grub-core/kern/uboot'
=== added file 'grub-core/kern/uboot/hw.c'
--- grub-core/kern/uboot/hw.c 1970-01-01 00:00:00 +0000
+++ grub-core/kern/uboot/hw.c 2013-03-24 12:58:23 +0000
@@ -0,0 +1,112 @@
+/* hw.c - U-Boot hardware discovery */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2013 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/kernel.h>
+#include <grub/memory.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/offsets.h>
+#include <grub/machine/kernel.h>
+#include <grub/uboot/disk.h>
+#include <grub/uboot/uboot.h>
+
+grub_addr_t start_of_ram;
+
+/*
+ * 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 = uboot_get_sys_info ();
+
+ grub_mm_init_region ((void *) (grub_modules_get_end ()
+ + GRUB_KERNEL_MACHINE_STACK_SIZE),
+ GRUB_KERNEL_MACHINE_HEAP_SIZE);
+
+ if (si && (si->mr_no != 0))
+ {
+ int i;
+ start_of_ram = GRUB_UINT_MAX;
+
+ for (i = 0; i < si->mr_no; i++)
+ if ((si->mr[i].flags & MR_ATTR_MASK) == MR_ATTR_DRAM)
+ if (si->mr[i].start < start_of_ram)
+ start_of_ram = si->mr[i].start;
+ }
+}
+
+/*
+ * grub_uboot_probe_hardware():
+ *
+ */
+grub_err_t
+grub_uboot_probe_hardware (void)
+{
+ int devcount, i;
+
+ devcount = uboot_dev_enum ();
+ grub_dprintf ("init", "%d devices found\n", devcount);
+
+ for (i = 0; i < devcount; i++)
+ {
+ struct device_info *devinfo = uboot_dev_get (i);
+
+ grub_dprintf ("init", "device handle: %d\n", i);
+ grub_dprintf ("init", " cookie\t= 0x%08x\n",
+ (grub_uint32_t) devinfo->cookie);
+
+ if (devinfo->type & DEV_TYP_STOR)
+ {
+ grub_dprintf ("init", " type\t\t= DISK\n");
+ grub_ubootdisk_register (devinfo, i);
+ }
+ else if (devinfo->type & DEV_TYP_NET)
+ {
+ grub_dprintf ("init", " type\t\t= NET (not supported yet)\n");
+ }
+ else
+ {
+ grub_dprintf ("init", "%s: unknown device type", __FUNCTION__);
+ }
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_machine_mmap_iterate (grub_memory_hook_t hook, void *hook_data)
+{
+ int i;
+ struct sys_info *si = uboot_get_sys_info ();
+
+ if (!si || (si->mr_no < 1))
+ return GRUB_ERR_BUG;
+
+ /* Iterate and call `hook'. */
+ for (i = 0; i < si->mr_no; i++)
+ if ((si->mr[i].flags & MR_ATTR_MASK) == MR_ATTR_DRAM)
+ hook (si->mr[i].start, si->mr[i].size, GRUB_MEMORY_AVAILABLE,
+ hook_data);
+
+ return GRUB_ERR_NONE;
+}
=== added file 'grub-core/kern/uboot/init.c'
--- grub-core/kern/uboot/init.c 1970-01-01 00:00:00 +0000
+++ grub-core/kern/uboot/init.c 2013-03-24 12:58:23 +0000
@@ -0,0 +1,171 @@
+/* init.c - generic U-Boot initialization and finalization */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2013 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 <http://www.gnu.org/licenses/>.
+ */
+
+
+#include <grub/env.h>
+#include <grub/kernel.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/offsets.h>
+#include <grub/term.h>
+#include <grub/time.h>
+#include <grub/machine/kernel.h>
+#include <grub/uboot/console.h>
+#include <grub/uboot/disk.h>
+#include <grub/uboot/uboot.h>
+
+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;
+
+void
+grub_exit (void)
+{
+ uboot_return (0);
+}
+
+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) uboot_get_timer (timer_start);
+}
+
+void
+grub_machine_init (void)
+{
+ grub_addr_t end, real_bss_start;
+ int ver;
+
+ /* First of all - establish connection with U-Boot */
+ ver = uboot_api_init ();
+ if (!ver)
+ {
+ /* Don't even have a console to log errors to... */
+ grub_exit ();
+ }
+ else if (ver > API_SIG_VERSION)
+ {
+ /* Try to print an error message */
+ uboot_puts ("invalid U-Boot API version\n");
+ }
+
+ /*
+ * Modules were relocated to _end, or __bss_start + grub_total_module_size,
+ * whichever greater. (And __bss_start may not point to actual BSS start...)
+ */
+ real_bss_start = uboot_get_real_bss_start ();
+ end = real_bss_start + grub_total_module_size;
+ if (end < (grub_addr_t) _end)
+ end = (grub_addr_t) _end;
+ grub_modbase = end;
+
+ /* Initialize the console so that GRUB can display messages. */
+ grub_console_init_early ();
+
+ /* Enumerate memory and initialize the memory management system. */
+ grub_uboot_mm_init ();
+
+ grub_dprintf ("init", "__bss_start: 0x%08x, real_bss_start: 0x%08x\n",
+ (grub_addr_t) __bss_start, real_bss_start);
+ grub_dprintf ("init", "end: 0x%08x, _end: 0x%08x\n",
+ (grub_addr_t) end, (grub_addr_t) _end);
+ grub_dprintf ("init", "grub_modbase: %p\n", (void *) grub_modbase);
+ grub_dprintf ("init", "grub_modules_get_end(): %p\n",
+ (void *) grub_modules_get_end ());
+
+ /* Initialise full terminfo support */
+ grub_console_init_lately ();
+
+ /* Enumerate uboot devices */
+ grub_uboot_probe_hardware ();
+
+ /* Initialise timer */
+ timer_start = uboot_get_timer (0);
+ grub_install_get_time_ms (uboot_timer_ms);
+
+ /* Initialize */
+ grub_ubootdisk_init ();
+}
+
+
+void
+grub_machine_fini (void)
+{
+}
+
+/*
+ * grub_machine_get_bootlocation():
+ * Called from kern/main.c, which expects a device name (minus parentheses)
+ * and a filesystem path back, if any are known.
+ * Any returned values must be pointers to dynamically allocated strings.
+ */
+void
+grub_machine_get_bootlocation (char **device, char **path)
+{
+ char *tmp;
+
+ tmp = uboot_env_get ("grub_bootdev");
+ if (tmp)
+ {
+ *device = grub_malloc (grub_strlen (tmp) + 1);
+ if (*device == NULL)
+ return;
+ grub_strncpy (*device, tmp, grub_strlen (tmp) + 1);
+ }
+ else
+ *device = NULL;
+
+ tmp = uboot_env_get ("grub_bootpath");
+ if (tmp)
+ {
+ *path = grub_malloc (grub_strlen (tmp) + 1);
+ if (*path == NULL)
+ return;
+ grub_strncpy (*path, tmp, grub_strlen (tmp) + 1);
+ }
+ else
+ *path = NULL;
+}
+
+void
+grub_uboot_fini (void)
+{
+ grub_ubootdisk_fini ();
+ grub_console_fini ();
+}
=== added file 'grub-core/kern/uboot/uboot.c'
--- grub-core/kern/uboot/uboot.c 1970-01-01 00:00:00 +0000
+++ grub-core/kern/uboot/uboot.c 2013-03-24 12:58:23 +0000
@@ -0,0 +1,363 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2013 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/uboot/uboot.h>
+
+/*
+ * The main syscall entry point is not reentrant, only one call is
+ * serviced until finished.
+ *
+ * int syscall(int call, int *retval, ...)
+ * e.g. syscall(1, int *, u_int32_t, u_int32_t, u_int32_t, u_int32_t);
+ *
+ * call: syscall number
+ *
+ * retval: points to the return value placeholder, this is the place the
+ * syscall puts its return value, if NULL the caller does not
+ * expect a return value
+ *
+ * ... syscall arguments (variable number)
+ *
+ * returns: 0 if the call not found, 1 if serviced
+ */
+
+extern int (*uboot_syscall_ptr) (int, int *, ...);
+extern int uboot_syscall (int, int *, ...);
+extern grub_addr_t uboot_search_hint;
+
+static struct sys_info uboot_sys_info;
+static struct mem_region uboot_mem_info[5];
+static struct device_info uboot_devices[6];
+static int num_devices;
+
+int
+uboot_api_init (void)
+{
+ struct api_signature *start, *end;
+ struct api_signature *p;
+
+ if (uboot_search_hint)
+ {
+ /* Extended search range to work around Trim Slice U-Boot issue */
+ start = (struct api_signature *) ((uboot_search_hint & ~0x000fffff)
+ - 0x00500000);
+ end =
+ (struct api_signature *) ((grub_addr_t) start + UBOOT_API_SEARCH_LEN -
+ API_SIG_MAGLEN + 0x00500000);
+ }
+ else
+ {
+ start = 0;
+ end = (struct api_signature *) (256 * 1024 * 1024);
+ }
+
+ /* Structure alignment is (at least) 8 bytes */
+ for (p = start; p < end; p = (void *) ((grub_addr_t) p + 8))
+ {
+ if (grub_memcmp (&(p->magic), API_SIG_MAGIC, API_SIG_MAGLEN) == 0)
+ {
+ uboot_syscall_ptr = p->syscall;
+ return p->version;
+ }
+ }
+
+ return 0;
+}
+
+/* All functions below are wrappers around the uboot_syscall() function */
+
+/*
+ * int API_getc(int *c)
+ */
+int
+uboot_getc (void)
+{
+ int c;
+ if (!uboot_syscall (API_GETC, NULL, &c))
+ return -1;
+
+ return c;
+}
+
+/*
+ * int API_tstc(int *c)
+ */
+int
+uboot_tstc (void)
+{
+ int c;
+ if (!uboot_syscall (API_TSTC, NULL, &c))
+ return -1;
+
+ return c;
+}
+
+/*
+ * int API_putc(char *ch)
+ */
+void
+uboot_putc (int c)
+{
+ uboot_syscall (API_PUTC, NULL, &c);
+}
+
+/*
+ * int API_puts(const char *s)
+ */
+void
+uboot_puts (const char *s)
+{
+ uboot_syscall (API_PUTS, NULL, s);
+}
+
+/*
+ * int API_reset(void)
+ */
+void
+uboot_reset (void)
+{
+ uboot_syscall (API_RESET, NULL, 0);
+}
+
+/*
+ * int API_get_sys_info(struct sys_info *si)
+ *
+ * fill out the sys_info struct containing selected parameters about the
+ * machine
+ */
+struct sys_info *
+uboot_get_sys_info (void)
+{
+ int retval;
+
+ grub_memset (&uboot_sys_info, 0, sizeof (uboot_sys_info));
+ grub_memset (&uboot_mem_info, 0, sizeof (uboot_mem_info));
+ uboot_sys_info.mr = uboot_mem_info;
+ uboot_sys_info.mr_no = sizeof (uboot_mem_info) / sizeof (struct mem_region);
+
+ if (uboot_syscall (API_GET_SYS_INFO, &retval, &uboot_sys_info))
+ if (retval == 0)
+ return &uboot_sys_info;
+
+ return NULL;
+}
+
+/*
+ * int API_udelay(unsigned long *udelay)
+ */
+void
+uboot_udelay (grub_uint32_t usec)
+{
+ uboot_syscall (API_UDELAY, NULL, &usec);
+}
+
+/*
+ * int API_get_timer(unsigned long *current, unsigned long *base)
+ */
+grub_uint32_t
+uboot_get_timer (grub_uint32_t base)
+{
+ grub_uint32_t current;
+
+ if (!uboot_syscall (API_GET_TIMER, NULL, ¤t, &base))
+ return 0;
+
+ return current;
+}
+
+/*
+ * int API_dev_enum(struct device_info *)
+ *
+ */
+int
+uboot_dev_enum (void)
+{
+ int max;
+
+ grub_memset (&uboot_devices, 0, sizeof (uboot_devices));
+ max = sizeof (uboot_devices) / sizeof (struct device_info);
+
+ /*
+ * The API_DEV_ENUM call starts a fresh enumeration when passed a
+ * struct device_info with a NULL cookie, and then depends on having
+ * the prevoiusly enumerated device cookie "seeded" into the target
+ * structure.
+ */
+ if (!uboot_syscall (API_DEV_ENUM, NULL, &uboot_devices)
+ || uboot_devices[0].cookie == NULL)
+ return 0;
+
+ for (num_devices = 1; num_devices < max; num_devices++)
+ {
+ uboot_devices[num_devices].cookie =
+ uboot_devices[num_devices - 1].cookie;
+ if (!uboot_syscall (API_DEV_ENUM, NULL, &uboot_devices[num_devices]))
+ return 0;
+
+ /* When no more devices to enumerate, target cookie set to NULL */
+ if (uboot_devices[num_devices].cookie == NULL)
+ break;
+ }
+
+ return num_devices;
+}
+
+#define VALID_DEV(x) (((x) < num_devices) && ((x) >= 0))
+#define OPEN_DEV(x) (VALID_DEV(x) && (uboot_devices[(x)].state == DEV_STA_OPEN))
+
+struct device_info *
+uboot_dev_get (int handle)
+{
+ if (VALID_DEV (handle))
+ return &uboot_devices[handle];
+
+ return NULL;
+}
+
+
+/*
+ * int API_dev_open(struct device_info *)
+ */
+int
+uboot_dev_open (int handle)
+{
+ struct device_info *dev;
+ int retval;
+
+ if (!VALID_DEV (handle))
+ return -1;
+
+ dev = &uboot_devices[handle];
+
+ if (!uboot_syscall (API_DEV_OPEN, &retval, dev))
+ return -1;
+
+ return retval;
+}
+
+/*
+ * int API_dev_close(struct device_info *)
+ */
+int
+uboot_dev_close (int handle)
+{
+ struct device_info *dev;
+ int retval;
+
+ if (!VALID_DEV (handle))
+ return -1;
+
+ dev = &uboot_devices[handle];
+
+ if (!uboot_syscall (API_DEV_CLOSE, &retval, dev))
+ return -1;
+
+ return retval;
+}
+
+
+/*
+ * int API_dev_read(struct device_info *di, void *buf, size_t *len,
+ * unsigned long *start, size_t *act_len)
+ */
+int
+uboot_dev_read (int handle, void *buf, lbasize_t blocks,
+ lbastart_t start, lbasize_t * real_blocks)
+{
+ struct device_info *dev;
+ int retval;
+
+ if (!OPEN_DEV (handle))
+ return -1;
+
+ dev = &uboot_devices[handle];
+
+ if (!uboot_syscall (API_DEV_READ, &retval, dev, buf,
+ &blocks, &start, real_blocks))
+ return -1;
+
+ return retval;
+}
+
+/*
+ * int API_dev_read(struct device_info *di, void *buf,
+ * size_t *len, size_t *act_len)
+ */
+int
+uboot_dev_recv (int handle, void *buf, int size, int *real_size)
+{
+ struct device_info *dev;
+ int retval;
+
+ if (!OPEN_DEV (handle))
+ return -1;
+
+ dev = &uboot_devices[handle];
+ if (!uboot_syscall (API_DEV_READ, &retval, dev, buf, &size, real_size))
+ return -1;
+
+ return retval;
+
+}
+
+/*
+ * Notice: this is for sending network packets only, as U-Boot does not
+ * support writing to storage at the moment (12.2007)
+ *
+ * int API_dev_write(struct device_info *di, void *buf, int *len)
+ */
+int
+uboot_dev_send (int handle, void *buf, int size)
+{
+ struct device_info *dev;
+ int retval;
+
+ if (!OPEN_DEV (handle))
+ return -1;
+
+ dev = &uboot_devices[handle];
+ if (!uboot_syscall (API_DEV_WRITE, &retval, dev, buf, &size))
+ return -1;
+
+ return retval;
+}
+
+/*
+ * int API_env_get(const char *name, char **value)
+ */
+char *
+uboot_env_get (const char *name)
+{
+ char *value;
+
+ if (!uboot_syscall (API_ENV_GET, NULL, name, &value))
+ return NULL;
+
+ return value;
+}
+
+/*
+ * int API_env_set(const char *name, const char *value)
+ */
+void
+uboot_env_set (const char *name, const char *value)
+{
+ uboot_syscall (API_ENV_SET, NULL, name, value);
+}
=== added directory 'grub-core/lib/uboot'
=== added file 'grub-core/lib/uboot/datetime.c'
--- grub-core/lib/uboot/datetime.c 1970-01-01 00:00:00 +0000
+++ grub-core/lib/uboot/datetime.c 2013-03-24 12:58:23 +0000
@@ -0,0 +1,41 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2013 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/types.h>
+#include <grub/symbol.h>
+#include <grub/uboot/uboot.h>
+#include <grub/datetime.h>
+#include <grub/dl.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+/* No simple platform-independent RTC access exists in U-Boot. */
+
+grub_err_t
+grub_get_datetime (struct grub_datetime *datetime __attribute__ ((unused)))
+{
+ return grub_error (GRUB_ERR_INVALID_COMMAND,
+ "can\'t get datetime using U-Boot");
+}
+
+grub_err_t
+grub_set_datetime (struct grub_datetime * datetime __attribute__ ((unused)))
+{
+ return grub_error (GRUB_ERR_INVALID_COMMAND,
+ "can\'t set datetime using U-Boot");
+}
=== added file 'grub-core/lib/uboot/halt.c'
--- grub-core/lib/uboot/halt.c 1970-01-01 00:00:00 +0000
+++ grub-core/lib/uboot/halt.c 2013-03-24 12:58:23 +0000
@@ -0,0 +1,31 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2013 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/kernel.h>
+
+void
+grub_halt (void)
+{
+ grub_machine_fini ();
+
+ /* Just stop here */
+
+ while (1);
+}
=== added file 'grub-core/lib/uboot/reboot.c'
--- grub-core/lib/uboot/reboot.c 1970-01-01 00:00:00 +0000
+++ grub-core/lib/uboot/reboot.c 2013-03-24 12:58:23 +0000
@@ -0,0 +1,30 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2013 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/kernel.h>
+#include <grub/misc.h>
+#include <grub/uboot/uboot.h>
+
+void
+grub_reboot (void)
+{
+ grub_machine_fini ();
+
+ uboot_reset ();
+ while (1);
+}
=== modified file 'grub-core/term/terminfo.c'
--- grub-core/term/terminfo.c 2013-03-05 19:00:51 +0000
+++ grub-core/term/terminfo.c 2013-03-24 12:58:23 +0000
@@ -745,7 +745,9 @@
static grub_extcmd_t cmd;
-#if defined (GRUB_MACHINE_IEEE1275) || defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_MIPS_QEMU_MIPS) || defined (GRUB_MACHINE_ARC)
+#if defined (GRUB_MACHINE_IEEE1275) || defined (GRUB_MACHINE_MIPS_LOONGSON) \
+ || defined (GRUB_MACHINE_MIPS_QEMU_MIPS) || defined (GRUB_MACHINE_ARC) \
+ || defined (GRUB_MACHINE_UBOOT)
void grub_terminfo_init (void)
#else
GRUB_MOD_INIT(terminfo)
=== added directory 'grub-core/term/uboot'
=== added file 'grub-core/term/uboot/console.c'
--- grub-core/term/uboot/console.c 1970-01-01 00:00:00 +0000
+++ grub-core/term/uboot/console.c 2013-03-24 12:58:23 +0000
@@ -0,0 +1,141 @@
+/* console.c - console interface layer for U-Boot platforms */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2013 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/term.h>
+#include <grub/misc.h>
+#include <grub/types.h>
+#include <grub/err.h>
+#include <grub/terminfo.h>
+#include <grub/uboot/uboot.h>
+#include <grub/uboot/console.h>
+
+static void
+put (struct grub_term_output *term __attribute__ ((unused)), const int c)
+{
+ uboot_putc (c);
+}
+
+static int
+readkey (struct grub_term_input *term __attribute__ ((unused)))
+{
+ if (uboot_tstc () > 0)
+ return uboot_getc ();
+
+ return -1;
+}
+
+static void
+uboot_console_setcursor (struct grub_term_output *term
+ __attribute__ ((unused)), int on
+ __attribute__ ((unused)))
+{
+ grub_terminfo_setcursor (term, on);
+}
+
+static grub_err_t
+uboot_console_init_input (struct grub_term_input *term)
+{
+ return grub_terminfo_input_init (term);
+}
+
+extern struct grub_terminfo_output_state uboot_console_terminfo_output;
+
+static void
+uboot_console_dimensions (void)
+{
+ /* Use a small console by default. */
+ if (!uboot_console_terminfo_output.width)
+ uboot_console_terminfo_output.width = 80;
+ if (!uboot_console_terminfo_output.height)
+ uboot_console_terminfo_output.height = 24;
+}
+
+static grub_err_t
+uboot_console_init_output (struct grub_term_output *term)
+{
+ uboot_console_dimensions ();
+
+ grub_terminfo_output_init (term);
+
+ return 0;
+}
+
+struct grub_terminfo_input_state uboot_console_terminfo_input = {
+ .readkey = readkey
+};
+
+struct grub_terminfo_output_state uboot_console_terminfo_output = {
+ .put = put,
+ .width = 80,
+ .height = 24
+};
+
+static struct grub_term_input uboot_console_term_input = {
+ .name = "console",
+ .init = uboot_console_init_input,
+ .getkey = grub_terminfo_getkey,
+ .data = &uboot_console_terminfo_input
+};
+
+static struct grub_term_output uboot_console_term_output = {
+ .name = "console",
+ .init = uboot_console_init_output,
+ .putchar = grub_terminfo_putchar,
+ .getwh = grub_terminfo_getwh,
+ .getxy = grub_terminfo_getxy,
+ .gotoxy = grub_terminfo_gotoxy,
+ .cls = grub_terminfo_cls,
+ .setcolorstate = grub_terminfo_setcolorstate,
+ .setcursor = uboot_console_setcursor,
+ .flags = GRUB_TERM_CODE_TYPE_ASCII,
+ .data = &uboot_console_terminfo_output,
+};
+
+void
+grub_console_init_early (void)
+{
+ grub_term_register_input ("console", &uboot_console_term_input);
+ grub_term_register_output ("console", &uboot_console_term_output);
+}
+
+
+/*
+ * grub_console_init_lately():
+ * Initializes terminfo formatting by registering terminal type.
+ * Called after heap has been configured.
+ *
+ */
+void
+grub_console_init_lately (void)
+{
+ const char *type;
+
+ /* See if explicitly set by U-Boot environment */
+ type = uboot_env_get ("grub_term");
+ if (!type)
+ type = "vt100";
+
+ grub_terminfo_init ();
+ grub_terminfo_output_register (&uboot_console_term_output, type);
+}
+
+void
+grub_console_fini (void)
+{
+}
=== modified file 'include/grub/disk.h'
--- include/grub/disk.h 2013-02-27 16:19:15 +0000
+++ include/grub/disk.h 2013-03-24 12:58:23 +0000
@@ -43,6 +43,7 @@
GRUB_DISK_DEVICE_CRYPTODISK_ID,
GRUB_DISK_DEVICE_ARCDISK_ID,
GRUB_DISK_DEVICE_HOSTDISK_ID,
+ GRUB_DISK_DEVICE_UBOOTDISK_ID,
};
struct grub_disk;
=== modified file 'include/grub/kernel.h'
--- include/grub/kernel.h 2013-03-07 07:17:24 +0000
+++ include/grub/kernel.h 2013-03-24 12:58:23 +0000
@@ -78,7 +78,7 @@
#if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) \
|| defined (GRUB_MACHINE_MULTIBOOT) || defined (GRUB_MACHINE_MIPS_QEMU_MIPS) \
|| defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_ARC) \
- || defined (__sparc__)
+ || defined (__sparc__) || defined (GRUB_MACHINE_UBOOT)
/* FIXME: stack is between 2 heap regions. Move it. */
#define GRUB_KERNEL_PRELOAD_SPACE_REUSABLE 1
#endif
=== added directory 'include/grub/uboot'
=== added file 'include/grub/uboot/api_public.h'
--- include/grub/uboot/api_public.h 1970-01-01 00:00:00 +0000
+++ include/grub/uboot/api_public.h 2013-03-24 12:58:23 +0000
@@ -0,0 +1,184 @@
+/*
+ * (C) Copyright 2007-2008 Semihalf
+ *
+ * Written by: Rafal Jaworowski <raj@semihalf.com>
+ *
+ * This file is dual licensed; you can use it under the terms of
+ * either the GPL, or the BSD license, at your option.
+ *
+ * I. GPL:
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Alternatively,
+ *
+ * II. BSD license:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _API_PUBLIC_H_
+#define _API_PUBLIC_H_
+
+#define API_EINVAL 1 /* invalid argument(s) */
+#define API_ENODEV 2 /* no device */
+#define API_ENOMEM 3 /* no memory */
+#define API_EBUSY 4 /* busy, occupied etc. */
+#define API_EIO 5 /* I/O error */
+#define API_ESYSC 6 /* syscall error */
+
+typedef int (*scp_t) (int, int *, ...);
+
+typedef grub_uint16_t uint16_t;
+typedef grub_uint32_t uint32_t;
+
+#define API_SIG_VERSION 1
+#define API_SIG_MAGIC "UBootAPI"
+#define API_SIG_MAGLEN 8
+
+struct api_signature
+{
+ char magic[API_SIG_MAGLEN]; /* magic string */
+ uint16_t version; /* API version */
+ uint32_t checksum; /* checksum of this sig struct */
+ scp_t syscall; /* entry point to the API */
+};
+
+enum
+{
+ API_RSVD = 0,
+ API_GETC,
+ API_PUTC,
+ API_TSTC,
+ API_PUTS,
+ API_RESET,
+ API_GET_SYS_INFO,
+ API_UDELAY,
+ API_GET_TIMER,
+ API_DEV_ENUM,
+ API_DEV_OPEN,
+ API_DEV_CLOSE,
+ API_DEV_READ,
+ API_DEV_WRITE,
+ API_ENV_ENUM,
+ API_ENV_GET,
+ API_ENV_SET,
+ API_DISPLAY_GET_INFO,
+ API_DISPLAY_DRAW_BITMAP,
+ API_DISPLAY_CLEAR,
+ API_MAXCALL
+};
+
+#define MR_ATTR_FLASH 0x0001
+#define MR_ATTR_DRAM 0x0002
+#define MR_ATTR_SRAM 0x0003
+#define MR_ATTR_MASK 0x000f
+
+struct mem_region
+{
+ unsigned long start;
+ unsigned long size;
+ int flags;
+};
+
+struct sys_info
+{
+ unsigned long clk_bus;
+ unsigned long clk_cpu;
+ unsigned long bar;
+ struct mem_region *mr;
+ int mr_no; /* number of memory regions */
+};
+
+#undef CONFIG_SYS_64BIT_LBA
+#ifdef CONFIG_SYS_64BIT_LBA
+typedef u_int64_t lbasize_t;
+#else
+typedef unsigned long lbasize_t;
+#endif
+typedef unsigned long lbastart_t;
+
+#define DEV_TYP_NONE 0x0000
+#define DEV_TYP_NET 0x0001
+
+#define DEV_TYP_STOR 0x0002
+#define DT_STOR_IDE 0x0010
+#define DT_STOR_SCSI 0x0020
+#define DT_STOR_USB 0x0040
+#define DT_STOR_MMC 0x0080
+#define DT_STOR_SATA 0x0100
+
+#define DEV_STA_CLOSED 0x0000 /* invalid, closed */
+#define DEV_STA_OPEN 0x0001 /* open i.e. active */
+
+struct device_info
+{
+ int type;
+ void *cookie;
+
+ union
+ {
+ struct
+ {
+ lbasize_t block_count; /* no of blocks */
+ unsigned long block_size; /* size of one block */
+ } storage;
+
+ struct
+ {
+ unsigned char hwaddr[6];
+ } net;
+ } info;
+#define di_stor info.storage
+#define di_net info.net
+
+ int state;
+};
+
+#define DISPLAY_TYPE_LCD 0x0001
+#define DISPLAY_TYPE_VIDEO 0x0002
+
+struct display_info
+{
+ int type;
+ /* screen size in pixels */
+ int pixel_width;
+ int pixel_height;
+ /* screen size in rows and columns of text */
+ int screen_rows;
+ int screen_cols;
+};
+
+#endif /* _API_PUBLIC_H_ */
=== added file 'include/grub/uboot/console.h'
--- include/grub/uboot/console.h 1970-01-01 00:00:00 +0000
+++ include/grub/uboot/console.h 2013-03-24 12:58:23 +0000
@@ -0,0 +1,29 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2013 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_CONSOLE_MACHINE_HEADER
+#define GRUB_CONSOLE_MACHINE_HEADER 1
+
+/* Initialize the console system. */
+void grub_console_init_early (void);
+void grub_console_init_lately (void);
+
+/* Exit the console system. */
+void grub_console_fini (void);
+
+#endif /* ! GRUB_CONSOLE_MACHINE_HEADER */
=== added file 'include/grub/uboot/disk.h'
--- include/grub/uboot/disk.h 1970-01-01 00:00:00 +0000
+++ include/grub/uboot/disk.h 2013-03-24 12:58:23 +0000
@@ -0,0 +1,44 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2013 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_UBOOT_DISK_HEADER
+#define GRUB_UBOOT_DISK_HEADER 1
+
+#include <grub/symbol.h>
+#include <grub/disk.h>
+#include <grub/uboot/uboot.h>
+
+void grub_ubootdisk_init (void);
+void grub_ubootdisk_fini (void);
+
+enum disktype
+{ cd, fd, hd };
+
+struct ubootdisk_data
+{
+ struct ubootdisk_data *next;
+ void *cookie;
+ int handle;
+ int opencount;
+ enum disktype type;
+ grub_uint32_t block_size;
+};
+
+grub_err_t grub_ubootdisk_register (struct device_info *newdev, int handle);
+
+#endif /* ! GRUB_UBOOT_DISK_HEADER */
=== added file 'include/grub/uboot/uboot.h'
--- include/grub/uboot/uboot.h 1970-01-01 00:00:00 +0000
+++ include/grub/uboot/uboot.h 2013-03-24 12:58:23 +0000
@@ -0,0 +1,150 @@
+/* uboot.h - declare variables and functions for U-Boot support */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2013 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_UBOOT_UBOOT_HEADER
+#define GRUB_UBOOT_UBOOT_HEADER 1
+
+#include <grub/types.h>
+#include <grub/dl.h>
+
+/* Functions. */
+void grub_uboot_mm_init (void);
+void grub_uboot_init (void);
+void grub_uboot_fini (void);
+
+void uboot_return (int) __attribute__ ((noreturn));
+
+grub_addr_t uboot_get_real_bss_start (void);
+
+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);
+
+
+/*
+ * The U-Boot API operates through a "syscall" interface, consisting of an
+ * entry point address and a set of syscall numbers. The location of this
+ * entry point is described in a structure allocated on the U-Boot heap.
+ * We scan through a defined region around the hint address passed to us
+ * from U-Boot.
+ */
+#include <grub/uboot/api_public.h>
+
+#define UBOOT_API_SEARCH_LEN (3 * 1024 * 1024)
+int uboot_api_init (void);
+
+/* All functions below are wrappers around the uboot_syscall() function */
+
+/*
+ * int API_getc(int *c)
+ */
+int uboot_getc (void);
+
+/*
+ * int API_tstc(int *c)
+ */
+int uboot_tstc (void);
+
+/*
+ * int API_putc(char *ch)
+ */
+void uboot_putc (int c);
+
+/*
+ * int API_puts(const char *s)
+ */
+void uboot_puts (const char *s);
+
+/*
+ * int API_reset(void)
+ */
+void EXPORT_FUNC (uboot_reset) (void);
+
+/*
+ * int API_get_sys_info(struct sys_info *si)
+ *
+ * fill out the sys_info struct containing selected parameters about the
+ * machine
+ */
+struct sys_info *uboot_get_sys_info (void);
+
+/*
+ * int API_udelay(unsigned long *udelay)
+ */
+void uboot_udelay (grub_uint32_t usec);
+
+/*
+ * int API_get_timer(unsigned long *current, unsigned long *base)
+ */
+grub_uint32_t uboot_get_timer (grub_uint32_t base);
+
+/*
+ * int API_dev_enum(struct device_info *)
+ */
+int uboot_dev_enum (void);
+
+struct device_info *uboot_dev_get (int handle);
+
+/*
+ * int API_dev_open(struct device_info *)
+ */
+int uboot_dev_open (int handle);
+
+/*
+ * int API_dev_close(struct device_info *)
+ */
+int uboot_dev_close (int handle);
+
+/*
+ * Notice: this is for sending network packets only, as U-Boot does not
+ * support writing to storage at the moment (12.2007)
+ *
+ * int API_dev_write(struct device_info *di, void *buf, int *len)
+ */
+int uboot_dev_write (int handle, void *buf, int *len);
+
+/*
+ * int API_dev_read(
+ * struct device_info *di,
+ * void *buf,
+ * size_t *len,
+ * unsigned long *start
+ * size_t *act_len
+ * )
+ */
+int uboot_dev_read (int handle, void *buf, lbasize_t blocks,
+ lbastart_t start, lbasize_t * real_blocks);
+
+int uboot_dev_recv (int handle, void *buf, int size, int *real_size);
+int uboot_dev_send (int handle, void *buf, int size);
+
+/*
+ * int API_env_get(const char *name, char **value)
+ */
+char *uboot_env_get (const char *name);
+
+/*
+ * int API_env_set(const char *name, const char *value)
+ */
+void uboot_env_set (const char *name, const char *value);
+
+#endif /* ! GRUB_UBOOT_UBOOT_HEADER */
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 3/7] Initial support for U-Boot platforms
2013-03-24 17:01 [PATCH 3/7] Initial support for U-Boot platforms Leif Lindholm
@ 2013-03-30 16:20 ` Francesco Lavra
2013-03-30 16:43 ` Vladimir 'φ-coder/phcoder' Serbinenko
2013-04-03 16:24 ` Leif Lindholm
2013-04-01 2:08 ` Vladimir 'φ-coder/phcoder' Serbinenko
1 sibling, 2 replies; 12+ messages in thread
From: Francesco Lavra @ 2013-03-30 16:20 UTC (permalink / raw)
To: grub-devel
Mostly cosmetic comments from my side here...
On 03/24/2013 06:01 PM, Leif Lindholm wrote:
[...]
> === added file 'grub-core/disk/uboot/ubootdisk.c'
> --- grub-core/disk/uboot/ubootdisk.c 1970-01-01 00:00:00 +0000
> +++ grub-core/disk/uboot/ubootdisk.c 2013-03-24 12:58:23 +0000
[...]
> +/*
> + * uboot_disk_iterate():
> + * Itarator over enumerated disk devices.
s/Itarator/Iterator
[...]
> === added file 'grub-core/kern/uboot/init.c'
> --- grub-core/kern/uboot/init.c 1970-01-01 00:00:00 +0000
> +++ grub-core/kern/uboot/init.c 2013-03-24 12:58:23 +0000
[...]
> +/*
> + * grub_machine_get_bootlocation():
> + * Called from kern/main.c, which expects a device name (minus parentheses)
> + * and a filesystem path back, if any are known.
> + * Any returned values must be pointers to dynamically allocated strings.
> + */
> +void
> +grub_machine_get_bootlocation (char **device, char **path)
> +{
> + char *tmp;
> +
> + tmp = uboot_env_get ("grub_bootdev");
> + if (tmp)
> + {
> + *device = grub_malloc (grub_strlen (tmp) + 1);
> + if (*device == NULL)
> + return;
> + grub_strncpy (*device, tmp, grub_strlen (tmp) + 1);
Why not simply call grub_strcpy (*device, tmp)?
> + }
> + else
> + *device = NULL;
> +
> + tmp = uboot_env_get ("grub_bootpath");
> + if (tmp)
> + {
> + *path = grub_malloc (grub_strlen (tmp) + 1);
> + if (*path == NULL)
> + return;
> + grub_strncpy (*path, tmp, grub_strlen (tmp) + 1);
Ditto, grub_strncpy is not needed.
> + }
> + else
> + *path = NULL;
> +}
> +
> +void
> +grub_uboot_fini (void)
> +{
> + grub_ubootdisk_fini ();
> + grub_console_fini ();
> +}
>
> === added file 'grub-core/kern/uboot/uboot.c'
> --- grub-core/kern/uboot/uboot.c 1970-01-01 00:00:00 +0000
> +++ grub-core/kern/uboot/uboot.c 2013-03-24 12:58:23 +0000
[...]
> +/* All functions below are wrappers around the uboot_syscall() function */
> +
> +/*
> + * int API_getc(int *c)
> + */
> +int
> +uboot_getc (void)
The comment preceding the function does not correspond to the function
prototype. This applies as well to all the subsequent functions in this
file.
[...]
> +int
> +uboot_dev_enum (void)
> +{
> + int max;
> +
> + grub_memset (&uboot_devices, 0, sizeof (uboot_devices));
> + max = sizeof (uboot_devices) / sizeof (struct device_info);
> +
> + /*
> + * The API_DEV_ENUM call starts a fresh enumeration when passed a
> + * struct device_info with a NULL cookie, and then depends on having
> + * the prevoiusly enumerated device cookie "seeded" into the target
s/prevoiusly/previously.
[...]
> === added file 'include/grub/uboot/uboot.h'
> --- include/grub/uboot/uboot.h 1970-01-01 00:00:00 +0000
> +++ include/grub/uboot/uboot.h 2013-03-24 12:58:23 +0000
> @@ -0,0 +1,150 @@
> +/* uboot.h - declare variables and functions for U-Boot support */
> +/*
> + * GRUB -- GRand Unified Bootloader
> + * Copyright (C) 2013 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 <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef GRUB_UBOOT_UBOOT_HEADER
> +#define GRUB_UBOOT_UBOOT_HEADER 1
> +
> +#include <grub/types.h>
> +#include <grub/dl.h>
> +
> +/* Functions. */
> +void grub_uboot_mm_init (void);
> +void grub_uboot_init (void);
> +void grub_uboot_fini (void);
> +
> +void uboot_return (int) __attribute__ ((noreturn));
> +
> +grub_addr_t uboot_get_real_bss_start (void);
> +
> +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);
> +
> +
> +/*
> + * The U-Boot API operates through a "syscall" interface, consisting of an
> + * entry point address and a set of syscall numbers. The location of this
> + * entry point is described in a structure allocated on the U-Boot heap.
> + * We scan through a defined region around the hint address passed to us
> + * from U-Boot.
> + */
> +#include <grub/uboot/api_public.h>
> +
> +#define UBOOT_API_SEARCH_LEN (3 * 1024 * 1024)
> +int uboot_api_init (void);
> +
> +/* All functions below are wrappers around the uboot_syscall() function */
> +
> +/*
> + * int API_getc(int *c)
> + */
> +int uboot_getc (void);
Same as for kern/uboot/uboot.c: the comments preceding the functions do
not correspond to the function prototypes.
--
Francesco
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 3/7] Initial support for U-Boot platforms
2013-03-30 16:20 ` Francesco Lavra
@ 2013-03-30 16:43 ` Vladimir 'φ-coder/phcoder' Serbinenko
2013-04-03 16:24 ` Leif Lindholm
1 sibling, 0 replies; 12+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2013-03-30 16:43 UTC (permalink / raw)
To: The development of GNU GRUB
[-- Attachment #1: Type: text/plain, Size: 144 bytes --]
On 30.03.2013 17:20, Francesco Lavra wrote:
> Why not simply call grub_strcpy (*device, tmp)?
Here you should use grub_Strdup actually
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 294 bytes --]
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 3/7] Initial support for U-Boot platforms
2013-03-30 16:20 ` Francesco Lavra
2013-03-30 16:43 ` Vladimir 'φ-coder/phcoder' Serbinenko
@ 2013-04-03 16:24 ` Leif Lindholm
2013-04-03 18:05 ` Lennart Sorensen
1 sibling, 1 reply; 12+ messages in thread
From: Leif Lindholm @ 2013-04-03 16:24 UTC (permalink / raw)
To: The development of GNU GRUB
On Sat, Mar 30, 2013 at 05:20:54PM +0100, Francesco Lavra wrote:
> Mostly cosmetic comments from my side here...
Typos will be fixed.
> On 03/24/2013 06:01 PM, Leif Lindholm wrote:
> [...]
> > === added file 'grub-core/kern/uboot/init.c'
> > --- grub-core/kern/uboot/init.c 1970-01-01 00:00:00 +0000
> > +++ grub-core/kern/uboot/init.c 2013-03-24 12:58:23 +0000
> [...]
> > +/*
> > + * grub_machine_get_bootlocation():
> > + * Called from kern/main.c, which expects a device name (minus parentheses)
> > + * and a filesystem path back, if any are known.
> > + * Any returned values must be pointers to dynamically allocated strings.
> > + */
> > +void
> > +grub_machine_get_bootlocation (char **device, char **path)
> > +{
> > + char *tmp;
> > +
> > + tmp = uboot_env_get ("grub_bootdev");
> > + if (tmp)
> > + {
> > + *device = grub_malloc (grub_strlen (tmp) + 1);
> > + if (*device == NULL)
> > + return;
> > + grub_strncpy (*device, tmp, grub_strlen (tmp) + 1);
>
> Why not simply call grub_strcpy (*device, tmp)?
Because I am an overtly paranoid person. :)
[...]
> > === added file 'grub-core/kern/uboot/uboot.c'
> > --- grub-core/kern/uboot/uboot.c 1970-01-01 00:00:00 +0000
> > +++ grub-core/kern/uboot/uboot.c 2013-03-24 12:58:23 +0000
> [...]
> > +/* All functions below are wrappers around the uboot_syscall() function */
> > +
> > +/*
> > + * int API_getc(int *c)
> > + */
> > +int
> > +uboot_getc (void)
>
> The comment preceding the function does not correspond to the function
> prototype. This applies as well to all the subsequent functions in this
> file.
This was a probably misguided way of showing what the "receiving end" of
the call ended up being (in U-Boot). I should either document this somewhere
or just drop these. Does anyone see any value in keeping them around?
> > === added file 'include/grub/uboot/uboot.h'
> > --- include/grub/uboot/uboot.h 1970-01-01 00:00:00 +0000
> > +++ include/grub/uboot/uboot.h 2013-03-24 12:58:23 +0000
[...]
> > +/* All functions below are wrappers around the uboot_syscall() function */
> > +
> > +/*
> > + * int API_getc(int *c)
> > + */
> > +int uboot_getc (void);
>
> Same as for kern/uboot/uboot.c: the comments preceding the functions do
> not correspond to the function prototypes.
Same reason. Same question.
/
Leif
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 3/7] Initial support for U-Boot platforms
2013-04-03 16:24 ` Leif Lindholm
@ 2013-04-03 18:05 ` Lennart Sorensen
2013-04-03 19:59 ` Vladimir 'φ-coder/phcoder' Serbinenko
0 siblings, 1 reply; 12+ messages in thread
From: Lennart Sorensen @ 2013-04-03 18:05 UTC (permalink / raw)
To: The development of GNU GRUB
On Wed, Apr 03, 2013 at 04:24:51PM +0000, Leif Lindholm wrote:
> Because I am an overtly paranoid person. :)
That's not paranoid. That's just inefficient. The length argument has
to be based on the target size, NOT the length of the source. If you want
to length of the source, that's what plain old strcpy does by definition.
I just found some of those in some other code I was cleaning up and
wasn't pleased with them there. Just because it says strncpy doesn't
mean what you are doing is any safer than strcpy if you do it wrong.
--
Len Sorensen
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 3/7] Initial support for U-Boot platforms
2013-03-24 17:01 [PATCH 3/7] Initial support for U-Boot platforms Leif Lindholm
2013-03-30 16:20 ` Francesco Lavra
@ 2013-04-01 2:08 ` Vladimir 'φ-coder/phcoder' Serbinenko
2013-04-03 16:17 ` Leif Lindholm
2013-05-02 19:25 ` Vladimir 'φ-coder/phcoder' Serbinenko
1 sibling, 2 replies; 12+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2013-04-01 2:08 UTC (permalink / raw)
To: The development of GNU GRUB
[-- Attachment #1: Type: text/plain, Size: 6318 bytes --]
On 24.03.2013 18:01, Leif Lindholm wrote:
About memory map:
It would make sense to put modules right before heap as module space is
reused later as heap if this is enabled.
> +#define STOR_TYPE(x) ((x) & 0x0ff0)
> + switch (STOR_TYPE (newdev->type))
> + {
> + case DT_STOR_IDE:
> + case DT_STOR_SATA:
> + /* hd */
> + type = hd;
> + break;
> + case DT_STOR_MMC:
> + case DT_STOR_USB:
> + /* fd */
> + type = fd;
> + break;
Problem is that --no-floppy would skip all those devices. This is
problem that uboot will be different from other platforms
> + d = (struct ubootdisk_data *) grub_malloc (sizeof (struct ubootdisk_data));
> + if (!d)
> + return GRUB_ERR_OUT_OF_MEMORY;
Just "return grub_errno;"
> +/* Helper function for uboot_disk_open. */
> +static struct ubootdisk_data *
> +get_device (struct ubootdisk_data *devices, int num)
> +{
> + struct ubootdisk_data *d;
> +
> + for (d = devices; d && num; d = d->next, num--)
> + ;
Why not just use an array and either double iteration to fill it (first
count, allocate, then fill) or double its size every time as needed
(like x2realloc)
> + /* Device has previously been enumerated, so this should never fail */
> + if ((devinfo = uboot_dev_get (d->handle)) == NULL)
> + goto fail;
Please put assignment before if.
> + disk->total_sectors = GRUB_DISK_SIZE_UNKNOWN;
Is there any way to get size from uboot?
> +static grub_err_t
> +uboot_disk_write (struct grub_disk *disk __attribute__ ((unused)),
> + grub_disk_addr_t sector __attribute__ ((unused)),
> + grub_size_t size __attribute__ ((unused)),
> + const char *buf __attribute__ ((unused)))
> +{
> + grub_dprintf ("ubootdisk", "attempt to write\n");
> + return GRUB_ERR_NOT_IMPLEMENTED_YET;
> +}
Could you make it use grub_error ?> +grub_uint32_t
> +uboot_get_machine_type (void)
> +{
> + return uboot_machine_type;
> +}
> +
Please use grub_ prefix for all global functions.
> +/*
> + * grub_machine_get_bootlocation():
> + * Called from kern/main.c, which expects a device name (minus parentheses)
> + * and a filesystem path back, if any are known.
> + * Any returned values must be pointers to dynamically allocated strings.
> + */
> +void
> +grub_machine_get_bootlocation (char **device, char **path)
> +{
> + char *tmp;
> +
> + tmp = uboot_env_get ("grub_bootdev");
> + if (tmp)
> + {
> + *device = grub_malloc (grub_strlen (tmp) + 1);
> + if (*device == NULL)
> + return;
> + grub_strncpy (*device, tmp, grub_strlen (tmp) + 1);
> + }
> + else
> + *device = NULL;
> +
> + tmp = uboot_env_get ("grub_bootpath");
> + if (tmp)
> + {
> + *path = grub_malloc (grub_strlen (tmp) + 1);
> + if (*path == NULL)
> + return;
> + grub_strncpy (*path, tmp, grub_strlen (tmp) + 1);
> + }
> + else
> + *path = NULL;
> +}
Why special variables for GRUB? Doesn't uboot tell where .elf was loaded
from.
> +extern int (*uboot_syscall_ptr) (int, int *, ...);
> +extern int uboot_syscall (int, int *, ...);
> +extern grub_addr_t uboot_search_hint;
Please grub_ prefix
> +/*
> + * int API_puts(const char *s)
> + */
> +void
> +uboot_puts (const char *s)
> +{
> + uboot_syscall (API_PUTS, NULL, s);
> +}
Why do you need puts rather than use xputs?
> + grub_memset (&uboot_sys_info, 0, sizeof (uboot_sys_info));
> + grub_memset (&uboot_mem_info, 0, sizeof (uboot_mem_info));
> + uboot_sys_info.mr = uboot_mem_info;
> + uboot_sys_info.mr_no = sizeof (uboot_mem_info) / sizeof (struct mem_region);
How is the size of this table chosen? Shouldn't you retry the call with
more entries if it fails?
> + * int API_dev_enum(struct device_info *)
> + *
> + */
> +int
> +uboot_dev_enum (void)
> +{
> + int max;
> +
> + grub_memset (&uboot_devices, 0, sizeof (uboot_devices));
> + max = sizeof (uboot_devices) / sizeof (struct device_info);
> +
Please avoid arbitrary limits. In this case it's better to export
iterator as-is and allow all users to store the results it uses.
Or use realloc in x2realloc algorithm
> +struct device_info *
> +uboot_dev_get (int handle)
> +{
> + if (VALID_DEV (handle))
> + return &uboot_devices[handle];
> +
> + return NULL;
> +}
> +
Why have handles and not just pass the structure through?
> +/* No simple platform-independent RTC access exists in U-Boot. */
> +
> +grub_err_t
> +grub_get_datetime (struct grub_datetime *datetime __attribute__ ((unused)))
> +{
> + return grub_error (GRUB_ERR_INVALID_COMMAND,
> + "can\'t get datetime using U-Boot");
GRUB_ERR_IO, not GRUB_ERR_INVALID_COMMAND. Perhaps it would be a good
thing to skip compiling all datetime users on uboot by defining a group
"datetime"
> +void
> +grub_halt (void)
> +{
> + grub_machine_fini ();
> +
> + /* Just stop here */
> +
Doesn't uboot have a way to shutdown a machine?
> +static void
> +uboot_console_setcursor (struct grub_term_output *term
> + __attribute__ ((unused)), int on
> + __attribute__ ((unused)))
> +{
> + grub_terminfo_setcursor (term, on);
> +}
Just use grub_terminfo_setcursor directly
> +
> +static grub_err_t
> +uboot_console_init_input (struct grub_term_input *term)
> +{
> + return grub_terminfo_input_init (term);
> +}
Likewise
> +static void
> +uboot_console_dimensions (void)
> +{
> + /* Use a small console by default. */
> + if (!uboot_console_terminfo_output.width)
> + uboot_console_terminfo_output.width = 80;
> + if (!uboot_console_terminfo_output.height)
> + uboot_console_terminfo_output.height = 24;
> +}
Does uboot interpret this consoel to the screen? You don't need to set
80x24 since it's already statically set to this value.
> + */
> +void
> +grub_console_init_lately (void)
> +{
> + const char *type;
> +
> + /* See if explicitly set by U-Boot environment */
> + type = uboot_env_get ("grub_term");
> + if (!type)
> + type = "vt100";
Why do you go for a variable rather than adding terminfo in configfile
if needed?
Does uboot interpret this console or is it relayed by serial? In former
case we probably need more appropriate console type
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 294 bytes --]
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 3/7] Initial support for U-Boot platforms
2013-04-01 2:08 ` Vladimir 'φ-coder/phcoder' Serbinenko
@ 2013-04-03 16:17 ` Leif Lindholm
2013-04-08 10:49 ` Vladimir 'φ-coder/phcoder' Serbinenko
2013-05-02 19:25 ` Vladimir 'φ-coder/phcoder' Serbinenko
1 sibling, 1 reply; 12+ messages in thread
From: Leif Lindholm @ 2013-04-03 16:17 UTC (permalink / raw)
To: The development of GNU GRUB; +Cc: phcoder
On Mon, Apr 01, 2013 at 04:08:59AM +0200, Vladimir '??-coder/phcoder' Serbinenko wrote:
> On 24.03.2013 18:01, Leif Lindholm wrote:
> About memory map:
> It would make sense to put modules right before heap as module space is
> reused later as heap if this is enabled.
So, move stack to after heap? Sure.
> > +#define STOR_TYPE(x) ((x) & 0x0ff0)
> > + switch (STOR_TYPE (newdev->type))
> > + {
> > + case DT_STOR_IDE:
> > + case DT_STOR_SATA:
> > + /* hd */
> > + type = hd;
> > + break;
> > + case DT_STOR_MMC:
> > + case DT_STOR_USB:
> > + /* fd */
> > + type = fd;
> > + break;
>
> Problem is that --no-floppy would skip all those devices. This is
> problem that uboot will be different from other platforms
Yes, sorry, I meant to get rid of that special case handling even after talking
to Colin back in November.
> > + d = (struct ubootdisk_data *) grub_malloc (sizeof (struct ubootdisk_data));
> > + if (!d)
> > + return GRUB_ERR_OUT_OF_MEMORY;
>
> Just "return grub_errno;"
>
> > +/* Helper function for uboot_disk_open. */
> > +static struct ubootdisk_data *
> > +get_device (struct ubootdisk_data *devices, int num)
> > +{
> > + struct ubootdisk_data *d;
> > +
> > + for (d = devices; d && num; d = d->next, num--)
> > + ;
>
> Why not just use an array and either double iteration to fill it (first
> count, allocate, then fill) or double its size every time as needed
> (like x2realloc)
>
> > + /* Device has previously been enumerated, so this should never fail */
> > + if ((devinfo = uboot_dev_get (d->handle)) == NULL)
> > + goto fail;
>
> Please put assignment before if.
>
> > + disk->total_sectors = GRUB_DISK_SIZE_UNKNOWN;
>
> Is there any way to get size from uboot?
Not that I've found. As in, not that can be relied on.
> > +static grub_err_t
> > +uboot_disk_write (struct grub_disk *disk __attribute__ ((unused)),
> > + grub_disk_addr_t sector __attribute__ ((unused)),
> > + grub_size_t size __attribute__ ((unused)),
> > + const char *buf __attribute__ ((unused)))
> > +{
> > + grub_dprintf ("ubootdisk", "attempt to write\n");
> > + return GRUB_ERR_NOT_IMPLEMENTED_YET;
> > +}
>
> Could you make it use grub_error ?> +grub_uint32_t
>
> > +uboot_get_machine_type (void)
> > +{
> > + return uboot_machine_type;
> > +}
> > +
>
> Please use grub_ prefix for all global functions.
Will do.
> > +/*
> > + * grub_machine_get_bootlocation():
> > + * Called from kern/main.c, which expects a device name (minus parentheses)
> > + * and a filesystem path back, if any are known.
> > + * Any returned values must be pointers to dynamically allocated strings.
> > + */
> > +void
> > +grub_machine_get_bootlocation (char **device, char **path)
> > +{
> > + char *tmp;
> > +
> > + tmp = uboot_env_get ("grub_bootdev");
> > + if (tmp)
> > + {
> > + *device = grub_malloc (grub_strlen (tmp) + 1);
> > + if (*device == NULL)
> > + return;
> > + grub_strncpy (*device, tmp, grub_strlen (tmp) + 1);
> > + }
> > + else
> > + *device = NULL;
> > +
> > + tmp = uboot_env_get ("grub_bootpath");
> > + if (tmp)
> > + {
> > + *path = grub_malloc (grub_strlen (tmp) + 1);
> > + if (*path == NULL)
> > + return;
> > + grub_strncpy (*path, tmp, grub_strlen (tmp) + 1);
> > + }
> > + else
> > + *path = NULL;
> > +}
>
> Why special variables for GRUB? Doesn't uboot tell where .elf was loaded
> from.
No, it's just an image loaded from memory as far as U-Boot is concerned.
That it might previously have been loaded from a filesystem is not kept
around anywhere. Anyway - this would only end up being used if the
embedded config failed.
> > +extern int (*uboot_syscall_ptr) (int, int *, ...);
> > +extern int uboot_syscall (int, int *, ...);
> > +extern grub_addr_t uboot_search_hint;
>
> Please grub_ prefix
>
> > +/*
> > + * int API_puts(const char *s)
> > + */
> > +void
> > +uboot_puts (const char *s)
> > +{
> > + uboot_syscall (API_PUTS, NULL, s);
> > +}
>
> Why do you need puts rather than use xputs?
To be honest, I don't end up calling it anywhere except for a very
early error message before the console is initialised. And that call
would likely fail.
It's provided by the API, so I implemeted the wrapper. Can drop?
> > + grub_memset (&uboot_sys_info, 0, sizeof (uboot_sys_info));
> > + grub_memset (&uboot_mem_info, 0, sizeof (uboot_mem_info));
> > + uboot_sys_info.mr = uboot_mem_info;
> > + uboot_sys_info.mr_no = sizeof (uboot_mem_info) / sizeof (struct mem_region);
>
> How is the size of this table chosen? Shouldn't you retry the call with
> more entries if it fails?
A bit lazily ...
The API_GET_SYS_INFO call returns the number of DRAM banks in the
system into this array. I can make it dynamic, but it is always
going to be a fairly low number (not like EFI).
> > + * int API_dev_enum(struct device_info *)
>
> > + *
> > + */
> > +int
> > +uboot_dev_enum (void)
> > +{
> > + int max;
> > +
> > + grub_memset (&uboot_devices, 0, sizeof (uboot_devices));
> > + max = sizeof (uboot_devices) / sizeof (struct device_info);
> > +
>
> Please avoid arbitrary limits. In this case it's better to export
> iterator as-is and allow all users to store the results it uses.
> Or use realloc in x2realloc algorithm
OK.
> > +struct device_info *
> > +uboot_dev_get (int handle)
> > +{
> > + if (VALID_DEV (handle))
> > + return &uboot_devices[handle];
> > +
> > + return NULL;
> > +}
> > +
>
> Why have handles and not just pass the structure through?
Originally to permit range checking. Superflouos?
> > +/* No simple platform-independent RTC access exists in U-Boot. */
> > +
> > +grub_err_t
> > +grub_get_datetime (struct grub_datetime *datetime __attribute__ ((unused)))
> > +{
> > + return grub_error (GRUB_ERR_INVALID_COMMAND,
> > + "can\'t get datetime using U-Boot");
>
> GRUB_ERR_IO, not GRUB_ERR_INVALID_COMMAND. Perhaps it would be a good
> thing to skip compiling all datetime users on uboot by defining a group
> "datetime"
That's certainly an option. Should I do that?
> > +void
> > +grub_halt (void)
> > +{
> > + grub_machine_fini ();
> > +
> > + /* Just stop here */
> > +
>
> Doesn't uboot have a way to shutdown a machine?
No. It has reset, but I couldn't convince myself that was more right than
just looping..
> > +static void
> > +uboot_console_setcursor (struct grub_term_output *term
> > + __attribute__ ((unused)), int on
> > + __attribute__ ((unused)))
> > +{
> > + grub_terminfo_setcursor (term, on);
> > +}
>
> Just use grub_terminfo_setcursor directly
>
> > +
> > +static grub_err_t
> > +uboot_console_init_input (struct grub_term_input *term)
> > +{
> > + return grub_terminfo_input_init (term);
> > +}
>
> Likewise
>
> > +static void
> > +uboot_console_dimensions (void)
> > +{
> > + /* Use a small console by default. */
> > + if (!uboot_console_terminfo_output.width)
> > + uboot_console_terminfo_output.width = 80;
> > + if (!uboot_console_terminfo_output.height)
> > + uboot_console_terminfo_output.height = 24;
> > +}
>
>
> Does uboot interpret this consoel to the screen? You don't need to set
> 80x24 since it's already statically set to this value.
Yeah, I might have been cargo culting ieee1275 around this region.
All changed as suggested.
> > + */
> > +void
> > +grub_console_init_lately (void)
> > +{
> > + const char *type;
> > +
> > + /* See if explicitly set by U-Boot environment */
> > + type = uboot_env_get ("grub_term");
> > + if (!type)
> > + type = "vt100";
>
> Why do you go for a variable rather than adding terminfo in configfile
> if needed?
> Does uboot interpret this console or is it relayed by serial? In former
> case we probably need more appropriate console type
No strong reason, I suppose.
Was useful during development.
Could drop.
/
Leif
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 3/7] Initial support for U-Boot platforms
2013-04-03 16:17 ` Leif Lindholm
@ 2013-04-08 10:49 ` Vladimir 'φ-coder/phcoder' Serbinenko
2013-04-09 10:37 ` Leif Lindholm
0 siblings, 1 reply; 12+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2013-04-08 10:49 UTC (permalink / raw)
To: Leif Lindholm; +Cc: The development of GNU GRUB
[-- Attachment #1: Type: text/plain, Size: 800 bytes --]
On 03.04.2013 18:17, Leif Lindholm wrote:
>>> + disk->total_sectors = GRUB_DISK_SIZE_UNKNOWN;
>> >
>> > Is there any way to get size from uboot?
> Not that I've found. As in, not that can be relied on.
>
di_stor.block_count works perfectly on my raspberry pi.
Any reason not to use it?
=== modified file 'grub-core/disk/uboot/ubootdisk.c'
--- grub-core/disk/uboot/ubootdisk.c 2013-04-07 00:41:07 +0000
+++ grub-core/disk/uboot/ubootdisk.c 2013-04-08 08:34:08 +0000
@@ -246,7 +246,7 @@
grub_dprintf ("ubootdisk", "(%s) blocksize=%d, log_sector_size=%d\n",
disk->name, d->block_size, disk->log_sector_size);
- disk->total_sectors = GRUB_DISK_SIZE_UNKNOWN;
+ disk->total_sectors = devinfo->di_stor.block_count;
disk->data = d;
return GRUB_ERR_NONE;
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 294 bytes --]
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 3/7] Initial support for U-Boot platforms
2013-04-08 10:49 ` Vladimir 'φ-coder/phcoder' Serbinenko
@ 2013-04-09 10:37 ` Leif Lindholm
2013-04-09 11:29 ` Vladimir 'φ-coder/phcoder' Serbinenko
0 siblings, 1 reply; 12+ messages in thread
From: Leif Lindholm @ 2013-04-09 10:37 UTC (permalink / raw)
To: Vladimir '??-coder/phcoder' Serbinenko
Cc: The development of GNU GRUB
On Mon, Apr 08, 2013 at 12:49:18PM +0200, Vladimir '??-coder/phcoder' Serbinenko wrote:
> On 03.04.2013 18:17, Leif Lindholm wrote:
>
> >>> + disk->total_sectors = GRUB_DISK_SIZE_UNKNOWN;
> >> >
> >> > Is there any way to get size from uboot?
> > Not that I've found. As in, not that can be relied on.
> >
>
> di_stor.block_count works perfectly on my raspberry pi.
> Any reason not to use it?
I did at one point have a platform reporting 0 here, but otherwise
functioning. This may have been platform initialisation issues though,
and something that you may consider should be resolved there rather than
dealt with in GRUB. I'm OK to include this.
> === modified file 'grub-core/disk/uboot/ubootdisk.c'
> --- grub-core/disk/uboot/ubootdisk.c 2013-04-07 00:41:07 +0000
> +++ grub-core/disk/uboot/ubootdisk.c 2013-04-08 08:34:08 +0000
> @@ -246,7 +246,7 @@
> grub_dprintf ("ubootdisk", "(%s) blocksize=%d, log_sector_size=%d\n",
> disk->name, d->block_size, disk->log_sector_size);
>
> - disk->total_sectors = GRUB_DISK_SIZE_UNKNOWN;
> + disk->total_sectors = devinfo->di_stor.block_count;
> disk->data = d;
>
> return GRUB_ERR_NONE;
/
Leif
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 3/7] Initial support for U-Boot platforms
2013-04-09 10:37 ` Leif Lindholm
@ 2013-04-09 11:29 ` Vladimir 'φ-coder/phcoder' Serbinenko
0 siblings, 0 replies; 12+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2013-04-09 11:29 UTC (permalink / raw)
To: Leif Lindholm; +Cc: The development of GNU GRUB
[-- Attachment #1: Type: text/plain, Size: 1407 bytes --]
On 09.04.2013 12:37, Leif Lindholm wrote:
> On Mon, Apr 08, 2013 at 12:49:18PM +0200, Vladimir '??-coder/phcoder' Serbinenko wrote:
>> On 03.04.2013 18:17, Leif Lindholm wrote:
>>
>>>>> + disk->total_sectors = GRUB_DISK_SIZE_UNKNOWN;
>>>>>
>>>>> Is there any way to get size from uboot?
>>> Not that I've found. As in, not that can be relied on.
>>>
>>
>> di_stor.block_count works perfectly on my raspberry pi.
>> Any reason not to use it?
>
> I did at one point have a platform reporting 0 here, but otherwise
> functioning. This may have been platform initialisation issues though,
> and something that you may consider should be resolved there rather than
> dealt with in GRUB. I'm OK to include this.
>
That's surely a U-Boot bug but we're accustomed to workarounding
firmware bugs. I'm OK with special-casing 0.
>> === modified file 'grub-core/disk/uboot/ubootdisk.c'
>> --- grub-core/disk/uboot/ubootdisk.c 2013-04-07 00:41:07 +0000
>> +++ grub-core/disk/uboot/ubootdisk.c 2013-04-08 08:34:08 +0000
>> @@ -246,7 +246,7 @@
>> grub_dprintf ("ubootdisk", "(%s) blocksize=%d, log_sector_size=%d\n",
>> disk->name, d->block_size, disk->log_sector_size);
>>
>> - disk->total_sectors = GRUB_DISK_SIZE_UNKNOWN;
>> + disk->total_sectors = devinfo->di_stor.block_count;
>> disk->data = d;
>>
>> return GRUB_ERR_NONE;
>
> /
> Leif
>
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 294 bytes --]
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 3/7] Initial support for U-Boot platforms
2013-04-01 2:08 ` Vladimir 'φ-coder/phcoder' Serbinenko
2013-04-03 16:17 ` Leif Lindholm
@ 2013-05-02 19:25 ` Vladimir 'φ-coder/phcoder' Serbinenko
1 sibling, 0 replies; 12+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2013-05-02 19:25 UTC (permalink / raw)
To: The development of GNU GRUB
[-- Attachment #1: Type: text/plain, Size: 341 bytes --]
On 01.04.2013 04:08, Vladimir 'φ-coder/phcoder' Serbinenko wrote:
> GRUB_ERR_IO, not GRUB_ERR_INVALID_COMMAND. Perhaps it would be a good
> thing to skip compiling all datetime users on uboot by defining a group
> "datetime"
After thinking, skipping compiling is probably not a good idea as it
will single-out U-boot even more.
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 294 bytes --]
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2013-05-02 19:25 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-03-24 17:01 [PATCH 3/7] Initial support for U-Boot platforms Leif Lindholm
2013-03-30 16:20 ` Francesco Lavra
2013-03-30 16:43 ` Vladimir 'φ-coder/phcoder' Serbinenko
2013-04-03 16:24 ` Leif Lindholm
2013-04-03 18:05 ` Lennart Sorensen
2013-04-03 19:59 ` Vladimir 'φ-coder/phcoder' Serbinenko
2013-04-01 2:08 ` Vladimir 'φ-coder/phcoder' Serbinenko
2013-04-03 16:17 ` Leif Lindholm
2013-04-08 10:49 ` Vladimir 'φ-coder/phcoder' Serbinenko
2013-04-09 10:37 ` Leif Lindholm
2013-04-09 11:29 ` Vladimir 'φ-coder/phcoder' Serbinenko
2013-05-02 19:25 ` Vladimir 'φ-coder/phcoder' Serbinenko
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).