cmd_boota.c 3.1 KB

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