uboot/board/MAI/AmigaOneG3SE/cmd_boota.c
<<
>>
Prefs
   1#include <common.h>
   2#include <command.h>
   3#include "../disk/part_amiga.h"
   4#include <asm/cache.h>
   5
   6DECLARE_GLOBAL_DATA_PTR;
   7
   8#undef BOOTA_DEBUG
   9
  10#ifdef BOOTA_DEBUG
  11#define PRINTF(fmt,args...)     printf (fmt ,##args)
  12#else
  13#define PRINTF(fmt,args...)
  14#endif
  15
  16struct block_header {
  17        u32 id;
  18        u32 summed_longs;
  19        s32 chk_sum;
  20};
  21
  22extern block_dev_desc_t *ide_get_dev (int dev);
  23extern struct bootcode_block *get_bootcode (block_dev_desc_t * dev_desc);
  24extern int sum_block (struct block_header *header);
  25
  26struct bootcode_block bblk;
  27
  28int do_boota (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
  29{
  30        unsigned char *load_address = (unsigned char *) CONFIG_SYS_LOAD_ADDR;
  31        unsigned char *base_address;
  32        unsigned long offset;
  33
  34        unsigned long part_number = 0;
  35        block_dev_desc_t *boot_disk;
  36        char *s;
  37        struct bootcode_block *boot_code;
  38
  39        /* Get parameters */
  40
  41        switch (argc) {
  42        case 2:
  43                load_address = (unsigned char *) simple_strtol (argv[1], NULL, 16);
  44                part_number = 0;
  45                break;
  46        case 3:
  47                load_address = (unsigned char *) simple_strtol (argv[1], NULL, 16);
  48                part_number = simple_strtol (argv[2], NULL, 16);
  49                break;
  50        }
  51
  52        base_address = load_address;
  53
  54        PRINTF ("Loading boot code from disk %d to %p\n", part_number,
  55                        load_address);
  56
  57        /* Find the appropriate disk device */
  58        boot_disk = ide_get_dev (part_number);
  59        if (!boot_disk) {
  60                PRINTF ("Unknown disk %d\n", part_number);
  61                return 1;
  62        }
  63
  64        /* Find the bootcode block */
  65        boot_code = get_bootcode (boot_disk);
  66        if (!boot_code) {
  67                PRINTF ("Not a bootable disk %d\n", part_number);
  68                return 1;
  69        }
  70
  71        /* Only use the offset from the first block */
  72        offset = boot_code->load_data[0];
  73        memcpy (load_address, &boot_code->load_data[1], 122 * 4);
  74        load_address += 122 * 4;
  75
  76        /* Setup for the loop */
  77        bblk.next = boot_code->next;
  78        boot_code = &bblk;
  79
  80        /* Scan the chain, and copy the loader succesively into the destination area */
  81        while (0xffffffff != boot_code->next) {
  82                PRINTF ("Loading block %d\n", boot_code->next);
  83
  84                /* Load block */
  85                if (1 !=
  86                        boot_disk->block_read (boot_disk->dev, boot_code->next, 1,
  87                                                                   (ulong *) & bblk)) {
  88                        PRINTF ("Read error\n");
  89                        return 1;
  90                }
  91
  92                /* check sum */
  93                if (sum_block ((struct block_header *) (ulong *) & bblk) != 0) {
  94                        PRINTF ("Checksum error\n");
  95                        return 1;
  96                }
  97
  98                /* Ok, concatenate it to the already loaded code */
  99                memcpy (load_address, boot_code->load_data, 123 * 4);
 100                load_address += 123 * 4;
 101        }
 102
 103        printf ("Bootcode loaded to %p (size %d)\n", base_address,
 104                        load_address - base_address);
 105        printf ("Entry point at %p\n", base_address + offset);
 106
 107        flush_cache (base_address, load_address - base_address);
 108
 109
 110        s = getenv ("autostart");
 111        if (s && strcmp (s, "yes") == 0) {
 112                void (*boot) (bd_t *, char *, block_dev_desc_t *);
 113                char *args;
 114
 115                boot = (void (*)(bd_t *, char *, block_dev_desc_t *)) (base_address + offset);
 116                boot (gd->bd, getenv ("amiga_bootargs"), boot_disk);
 117        }
 118
 119
 120        return 0;
 121}
 122#if defined(CONFIG_AMIGAONEG3SE) && defined(CONFIG_CMD_BSP)
 123U_BOOT_CMD(
 124        boota,   3,      1,      do_boota,
 125        "boot an Amiga kernel",
 126        "address disk"
 127);
 128#endif /* _CMD_BOOTA_H */
 129