You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

eltorito.c 3.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. #include <etherboot.h>
  2. #include <fs.h>
  3. #include <lib.h>
  4. #define DEBUG_THIS DEBUG_ELTORITO
  5. #include <debug.h>
  6. #define ELTORITO_PLATFORM_X86 0
  7. #define ELTORITO_PLATFORM_PPC 1
  8. #define ELTORITO_PLATFORM_MAC 2
  9. #include <bits/eltorito.h>
  10. #ifndef ELTORITO_PLATFORM
  11. #error "ELTORITO_PLATFORM is not defined for this arch"
  12. #endif
  13. /* El Torito boot record at sector 0x11 of bootable CD */
  14. struct boot_record {
  15. uint8_t ind;
  16. uint8_t iso_id[5];
  17. uint8_t version;
  18. uint8_t boot_id[32];
  19. uint8_t reserved[32];
  20. uint8_t catalog_offset[4];
  21. };
  22. /* First entry of the catalog */
  23. struct validation_entry {
  24. uint8_t header_id;
  25. uint8_t platform;
  26. uint8_t reserved[2];
  27. uint8_t id[24];
  28. uint8_t checksum[2];
  29. uint8_t key55;
  30. uint8_t keyAA;
  31. };
  32. /* Initial/Default catalog entry */
  33. struct default_entry {
  34. uint8_t boot_id;
  35. uint8_t media_type;
  36. #define MEDIA_MASK 0x0f
  37. #define MEDIA_NOEMU 0
  38. #define MEDIA_1200_FD 1
  39. #define MEDIA_1440_FD 2
  40. #define MEDIA_2880_FD 3
  41. #define MEDIA_HD 4
  42. uint8_t load_segment[2];
  43. uint8_t system_type;
  44. uint8_t reserved;
  45. uint8_t sector_count[2];
  46. uint8_t start_sector[4];
  47. uint8_t reserved_too[20];
  48. };
  49. /* Find El-Torito boot disk image */
  50. int open_eltorito_image(int part, unsigned long *offset_p,
  51. unsigned long *length_p)
  52. {
  53. struct boot_record boot_record;
  54. uint32_t cat_offset;
  55. uint8_t catalog[2048];
  56. struct validation_entry *ve;
  57. int i, sum;
  58. struct default_entry *de;
  59. /* We always use 512-byte "soft sector", but
  60. * El-Torito uses 2048-byte CD-ROM sector */
  61. /* Boot Record is at sector 0x11 */
  62. if (!devread(0x11<<2, 0, sizeof boot_record, &boot_record))
  63. return 0;
  64. if (boot_record.ind != 0
  65. || memcmp(boot_record.iso_id, "CD001", 5) != 0
  66. || memcmp(boot_record.boot_id, "EL TORITO SPECIFICATION", 23)
  67. != 0) {
  68. debug("No El-Torito signature\n");
  69. return PARTITION_UNKNOWN;
  70. }
  71. if (part != 0) {
  72. printf("El-Torito entries other than Initial/Default is not supported\n");
  73. return 0;
  74. }
  75. cat_offset = get_le32(boot_record.catalog_offset);
  76. debug("El-Torito boot catalog at sector %u\n", cat_offset);
  77. if (!devread(cat_offset<<2, 0, 2048, catalog))
  78. return 0;
  79. /* Validate the catalog */
  80. ve = (void *) catalog;
  81. //debug_hexdump(ve, sizeof *ve);
  82. if (ve->header_id != 1 || ve->key55 != 0x55 || ve->keyAA != 0xAA) {
  83. printf("Invalid El Torito boot catalog\n");
  84. return 0;
  85. }
  86. /* All words must sum up to zero */
  87. sum = 0;
  88. for (i = 0; i < sizeof(*ve); i += 2)
  89. sum += get_le16(&catalog[i]);
  90. sum &= 0xffff;
  91. if (sum != 0) {
  92. printf("El Torito boot catalog verify failed\n");
  93. return 0;
  94. }
  95. debug("id='%.*s'\n", sizeof ve->id, ve->id);
  96. /* Platform check is warning only, because we won't directly execute
  97. * the image. Just mounting it should be safe. */
  98. if (ve->platform != ELTORITO_PLATFORM){
  99. debugx("WARNING: Boot disk for different platform: %d\n", ve->platform);
  100. }
  101. /* Just support initial/default entry for now */
  102. de = (void *) (ve + 1);
  103. if (de->boot_id != 0x88) {
  104. debugx("WARNING: Default boot entry is not bootable\n");
  105. }
  106. switch (de->media_type & MEDIA_MASK) {
  107. case MEDIA_NOEMU:
  108. printf("Disc doesn't use boot disk emulation\n");
  109. return 0;
  110. case MEDIA_1200_FD:
  111. *length_p = 1200*1024/512;
  112. break;
  113. case MEDIA_1440_FD:
  114. *length_p = 1440*1024/512;
  115. break;
  116. case MEDIA_2880_FD:
  117. *length_p = 2880*1024/512;
  118. break;
  119. case MEDIA_HD:
  120. /* FIXME: read partition table and return first partition.
  121. * Spec states emulation HD has only one partition and it must
  122. * be the first partition */
  123. printf("Disc uses hard disk emulation - not supported\n");
  124. return 0;
  125. }
  126. *offset_p = get_le32(de->start_sector) << 2;
  127. debug("offset=%#lx length=%#lx\n", *offset_p, *length_p);
  128. return 1;
  129. }