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