]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/MAI/AmigaOneG3SE/cmd_boota.c
imported Freescale specific U-Boot additions for i.MX28,... release L2.6.31_10.08.01
[karo-tx-uboot.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 DECLARE_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
16 struct block_header {
17         u32 id;
18         u32 summed_longs;
19         s32 chk_sum;
20 };
21
22 extern block_dev_desc_t *ide_get_dev (int dev);
23 extern struct bootcode_block *get_bootcode (block_dev_desc_t * dev_desc);
24 extern int sum_block (struct block_header *header);
25
26 struct bootcode_block bblk;
27
28 int 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)
123 U_BOOT_CMD(
124         boota,   3,      1,      do_boota,
125         "boot an Amiga kernel",
126         "address disk"
127 );
128 #endif /* _CMD_BOOTA_H */