cmd_boota.c 3.0 KB

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