* Patch by Thomas Frieden, 13 Nov 2002:
  Add code for AmigaOne board
  (preliminary merge to U-Boot, still WIP)

* Patch by Jon Diekema, 12 Nov 2002:
  - Adding URL for IEEE OUI lookup
  - Making the autoboot #defines dependent on CONFIG_AUTOBOOT_KEYED
    being defined.
  - In the CONFIG_EXTRA_ENV_SETTINGS #define, the root-on-initrd and
    root-on-nfs macros are designed to switch how the default boot
    method gets defined.
diff --git a/board/MAI/AmigaOneG3SE/cmd_boota.c b/board/MAI/AmigaOneG3SE/cmd_boota.c
new file mode 100644
index 0000000..140aaff
--- /dev/null
+++ b/board/MAI/AmigaOneG3SE/cmd_boota.c
@@ -0,0 +1,123 @@
+#include <common.h>
+#include <command.h>
+#include <cmd_boota.h>
+#include "../disk/part_amiga.h"
+#include <asm/cache.h>
+
+
+#undef BOOTA_DEBUG
+
+#ifdef BOOTA_DEBUG
+#define PRINTF(fmt,args...)	printf (fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+struct block_header {
+	u32 id;
+	u32 summed_longs;
+	s32 chk_sum;
+};
+
+extern block_dev_desc_t *ide_get_dev (int dev);
+extern struct bootcode_block *get_bootcode (block_dev_desc_t * dev_desc);
+extern int sum_block (struct block_header *header);
+
+struct bootcode_block bblk;
+
+int do_boota (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
+{
+	unsigned char *load_address = (unsigned char *) CFG_LOAD_ADDR;
+	unsigned char *base_address;
+	unsigned long offset;
+
+	unsigned long part_number = 0;
+	block_dev_desc_t *boot_disk;
+	char *s;
+	struct bootcode_block *boot_code;
+
+	/* Get parameters */
+
+	switch (argc) {
+	case 2:
+		load_address = (unsigned char *) simple_strtol (argv[1], NULL, 16);
+		part_number = 0;
+		break;
+	case 3:
+		load_address = (unsigned char *) simple_strtol (argv[1], NULL, 16);
+		part_number = simple_strtol (argv[2], NULL, 16);
+		break;
+	}
+
+	base_address = load_address;
+
+	PRINTF ("Loading boot code from disk %d to %p\n", part_number,
+			load_address);
+
+	/* Find the appropriate disk device */
+	boot_disk = ide_get_dev (part_number);
+	if (!boot_disk) {
+		PRINTF ("Unknown disk %d\n", part_number);
+		return 1;
+	}
+
+	/* Find the bootcode block */
+	boot_code = get_bootcode (boot_disk);
+	if (!boot_code) {
+		PRINTF ("Not a bootable disk %d\n", part_number);
+		return 1;
+	}
+
+	/* Only use the offset from the first block */
+	offset = boot_code->load_data[0];
+	memcpy (load_address, &boot_code->load_data[1], 122 * 4);
+	load_address += 122 * 4;
+
+	/* Setup for the loop */
+	bblk.next = boot_code->next;
+	boot_code = &bblk;
+
+	/* Scan the chain, and copy the loader succesively into the destination area */
+	while (0xffffffff != boot_code->next) {
+		PRINTF ("Loading block %d\n", boot_code->next);
+
+		/* Load block */
+		if (1 !=
+			boot_disk->block_read (boot_disk->dev, boot_code->next, 1,
+								   (ulong *) & bblk)) {
+			PRINTF ("Read error\n");
+			return 1;
+		}
+
+		/* check sum */
+		if (sum_block ((struct block_header *) (ulong *) & bblk) != 0) {
+			PRINTF ("Checksum error\n");
+			return 1;
+		}
+
+		/* Ok, concatenate it to the already loaded code */
+		memcpy (load_address, boot_code->load_data, 123 * 4);
+		load_address += 123 * 4;
+	}
+
+	printf ("Bootcode loaded to %p (size %d)\n", base_address,
+			load_address - base_address);
+	printf ("Entry point at %p\n", base_address + offset);
+
+	flush_cache (base_address, load_address - base_address);
+
+
+	s = getenv ("autostart");
+	if (s && strcmp (s, "yes") == 0) {
+		DECLARE_GLOBAL_DATA_PTR;
+
+		void (*boot) (bd_t *, char *, block_dev_desc_t *);
+		char *args;
+
+		boot = (void (*)(bd_t *, char *, block_dev_desc_t *)) (base_address + offset);
+		boot (gd->bd, getenv ("amiga_bootargs"), boot_disk);
+	}
+
+
+	return 0;
+}