blob: 6b955d8352198cc578793e4f272e7743db1784d9 [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
Wolfgang Denk6405a152006-03-31 18:32:53 +02006DECLARE_GLOBAL_DATA_PTR;
wdenk452cfd62002-11-19 11:04:11 +00007
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{
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020030 unsigned char *load_address = (unsigned char *) CONFIG_SYS_LOAD_ADDR;
wdenk452cfd62002-11-19 11:04:11 +000031 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) {
wdenk452cfd62002-11-19 11:04:11 +0000112 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}
Jon Loeligerd299abc2007-07-09 18:19:09 -0500122#if defined(CONFIG_AMIGAONEG3SE) && defined(CONFIG_CMD_BSP)
wdenkf287a242003-07-01 21:06:45 +0000123U_BOOT_CMD(
124 boota, 3, 1, do_boota,
Peter Tyserdfb72b82009-01-27 18:03:12 -0600125 "boot an Amiga kernel",
wdenk57b2d802003-06-27 21:31:46 +0000126 "address disk"
127);
128#endif /* _CMD_BOOTA_H */