blob: 3e2835aaeba5a12554905bdd6c6c73ffee50d03a [file] [log] [blame]
wdenk452cfd62002-11-19 11:04:11 +00001#include <common.h>
2#include <command.h>
wdenk452cfd62002-11-19 11:04:11 +00003#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
15struct block_header {
16 u32 id;
17 u32 summed_longs;
18 s32 chk_sum;
19};
20
21extern block_dev_desc_t *ide_get_dev (int dev);
22extern struct bootcode_block *get_bootcode (block_dev_desc_t * dev_desc);
23extern int sum_block (struct block_header *header);
24
25struct bootcode_block bblk;
26
27int 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}
wdenk57b2d802003-06-27 21:31:46 +0000123#if defined(CONFIG_AMIGAONEG3SE) && (CONFIG_COMMANDS & CFG_CMD_BSP)
wdenkf287a242003-07-01 21:06:45 +0000124U_BOOT_CMD(
125 boota, 3, 1, do_boota,
wdenk57b2d802003-06-27 21:31:46 +0000126 "boota - boot an Amiga kernel\n",
127 "address disk"
128);
129#endif /* _CMD_BOOTA_H */