Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

disk.c 6.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. #include "etherboot.h"
  2. #include "disk.h"
  3. #warning "disk.c is currently broken"
  4. #if 0
  5. #undef disk_disable
  6. static int dummy(void *unused __unused)
  7. {
  8. return (0);
  9. }
  10. static unsigned char disk_buffer[DISK_BUFFER_SIZE];
  11. struct disk disk =
  12. {
  13. {
  14. 0, /* dev.disable */
  15. {
  16. 0,
  17. 0,
  18. PCI_BUS_TYPE,
  19. }, /* dev.devid */
  20. 0, /* index */
  21. 0, /* type */
  22. PROBE_FIRST, /* how_probe */
  23. PROBE_NONE, /* to_probe */
  24. 0, /* failsafe */
  25. 0, /* type_index */
  26. {}, /* state */
  27. },
  28. (int (*)(struct disk *, sector_t ))dummy, /* read */
  29. 0 - 1, /* drive */
  30. 0, /* hw_sector_size */
  31. 0, /* sectors_per_read */
  32. 0, /* bytes */
  33. 0, /* sectors */
  34. 0, /* sector */
  35. disk_buffer, /* buffer */
  36. 0, /* priv */
  37. 0, /* disk_offset */
  38. 0, /* direction */
  39. };
  40. static int disk_read(
  41. struct disk *disk, unsigned char *buffer, sector_t sector)
  42. {
  43. int result;
  44. sector_t base_sector;
  45. /* Note: I do not handle disk wrap around here! */
  46. /* Compute the start of the track cache */
  47. base_sector = sector;
  48. /* Support sectors_per_read > 1 only on small disks */
  49. if ((sizeof(sector_t) > sizeof(unsigned long)) &&
  50. (disk->sectors_per_read > 1)) {
  51. unsigned long offset;
  52. offset = ((unsigned long)sector) % disk->sectors_per_read;
  53. base_sector -= offset;
  54. }
  55. /* See if I need to update the track cache */
  56. if ((sector < disk->sector) ||
  57. sector >= disk->sector + (disk->bytes >> 9)) {
  58. twiddle();
  59. result = disk->read(disk, base_sector);
  60. if (result < 0)
  61. return result;
  62. }
  63. /* Service the request from the track cache */
  64. memcpy(buffer, disk->buffer + ((sector - base_sector)<<9), SECTOR_SIZE);
  65. return 0;
  66. }
  67. static int disk_read_sectors(
  68. struct disk *disk,
  69. unsigned char *buffer,
  70. sector_t base_sector, unsigned int sectors)
  71. {
  72. sector_t sector = 0;
  73. unsigned long offset;
  74. int result = 0;
  75. for(offset = 0; offset < sectors; offset++) {
  76. sector = base_sector + offset;
  77. if (sector >= disk->sectors) {
  78. sector -= disk->sectors;
  79. }
  80. result = disk_read(disk, buffer + (offset << 9), sector);
  81. if (result < 0)
  82. break;
  83. }
  84. if (result < 0) {
  85. printf("disk read error at 0x%lx\n", sector);
  86. }
  87. return result;
  88. }
  89. static os_download_t probe_buffer(unsigned char *buffer, unsigned int len,
  90. int increment, unsigned int offset, unsigned int *roffset)
  91. {
  92. os_download_t os_download;
  93. unsigned int end;
  94. end = 0;
  95. os_download = 0;
  96. if (increment > 0) {
  97. end = len - SECTOR_SIZE;
  98. }
  99. do {
  100. offset += increment;
  101. os_download = probe_image(buffer + offset, len - offset);
  102. } while(!os_download && (offset != end));
  103. *roffset = offset;
  104. return os_download;
  105. }
  106. static int load_image(
  107. struct disk *disk,
  108. unsigned char *buffer, unsigned int buf_sectors,
  109. sector_t block, unsigned int offset,
  110. os_download_t os_download)
  111. {
  112. sector_t skip_sectors;
  113. skip_sectors = 0;
  114. while(1) {
  115. skip_sectors = os_download(buffer + offset,
  116. (buf_sectors << 9) - offset, 0);
  117. block += skip_sectors + buf_sectors;
  118. if (block >= disk->sectors) {
  119. block -= disk->sectors;
  120. }
  121. offset = 0;
  122. buf_sectors = 1;
  123. if (disk_read_sectors(disk, buffer, block, 1) < 0) {
  124. return 0;
  125. }
  126. }
  127. return -1;
  128. }
  129. int disk_probe(struct dev *dev)
  130. {
  131. struct disk *disk = (struct disk *)dev;
  132. if (dev->how_probe == PROBE_NEXT) {
  133. disk->drive += 1;
  134. }
  135. return probe(dev);
  136. }
  137. int disk_load_configuration(struct dev *dev)
  138. {
  139. /* Start with the very simplest possible disk configuration */
  140. struct disk *disk = (struct disk *)dev;
  141. disk->direction = (dev->failsafe)?-1:1;
  142. disk->disk_offset = 0;
  143. return 0;
  144. }
  145. int disk_load(struct dev *dev)
  146. {
  147. struct disk *disk = (struct disk *)dev;
  148. /* 16K == 8K in either direction from the start of the disk */
  149. static unsigned char buffer[32*SECTOR_SIZE];
  150. os_download_t os_download;
  151. unsigned int offset;
  152. unsigned int len;
  153. unsigned int buf_sectors;
  154. volatile sector_t block;
  155. volatile int inc, increment;
  156. int i;
  157. int result;
  158. jmp_buf real_restart;
  159. printf("Searching for image...\n");
  160. result = 0;
  161. /* Only check for 16byte aligned images */
  162. increment = (disk->direction < 0)?-16:16;
  163. /* Load a buffer, and see if it contains the start of an image
  164. * we can boot from disk.
  165. */
  166. len = sizeof(buffer);
  167. buf_sectors = sizeof(buffer) / SECTOR_SIZE;
  168. inc = increment;
  169. block = (disk->disk_offset) >> 9;
  170. if (buf_sectors/2 > block) {
  171. block = (disk->sectors - (buf_sectors/2)) + block;
  172. }
  173. /* let probe buffer assume offset always needs to be incremented */
  174. offset = (len/2 + ((disk->disk_offset) & 0x1ff)) - inc;
  175. /* Catch longjmp so if this image fails to load, I start looking
  176. * for the next image where I left off looking for this image.
  177. */
  178. memcpy(&real_restart, &restart_etherboot, sizeof(jmp_buf));
  179. i = setjmp(restart_etherboot);
  180. if ((i != 0) && (i != -2)) {
  181. memcpy(&restart_etherboot, &real_restart, sizeof(jmp_buf));
  182. longjmp(restart_etherboot, i);
  183. }
  184. /* Read the canidate sectors into the buffer */
  185. if (disk_read_sectors(disk, buffer, block, buf_sectors) < 0) {
  186. result = -1;
  187. goto out;
  188. }
  189. if (inc == increment) {
  190. os_download = probe_buffer(buffer, len, inc, offset, &offset);
  191. if (os_download)
  192. goto load_image;
  193. inc = -inc;
  194. }
  195. os_download = probe_buffer(buffer, len, inc, offset, &offset);
  196. if (!os_download) {
  197. result = -1;
  198. goto out;
  199. }
  200. load_image:
  201. printf("Loading image...\n");
  202. result = load_image(disk, buffer, buf_sectors, block, offset, os_download);
  203. out:
  204. memcpy(&restart_etherboot, &real_restart, sizeof(jmp_buf));
  205. return result;
  206. }
  207. int url_file(const char *name,
  208. int (*fnc)(unsigned char *, unsigned int, unsigned int, int) __unused)
  209. {
  210. unsigned int drive;
  211. unsigned long disk_offset;
  212. int direction;
  213. int type;
  214. disk_offset = 0;
  215. direction = 1;
  216. if (memcmp(name, "disk", 4) == 0) {
  217. type = DISK_DRIVER;
  218. name += 4;
  219. }
  220. else if (memcmp(name, "floppy", 6) == 0) {
  221. type = FLOPPY_DRIVER;
  222. name += 6;
  223. }
  224. else {
  225. printf("Unknown device type\n");
  226. return 0;
  227. }
  228. drive = strtoul(name, &name, 10);
  229. if ((name[0] == '+') || (name[0] == '-')) {
  230. direction = (name[0] == '-')? -1 : 1;
  231. name++;
  232. disk_offset = strtoul(name, &name, 10);
  233. }
  234. if (name[0]) {
  235. printf("Junk '%s' at end of disk url\n", name);
  236. return 0;
  237. }
  238. memset(&disk, 0, sizeof(disk));
  239. disk.buffer = disk_buffer;
  240. disk.drive = 0;
  241. disk.dev.how_probe = PROBE_FIRST;
  242. disk.dev.type = type;
  243. do {
  244. disk_disable();
  245. disk.dev.how_probe = disk_probe(&disk.dev);
  246. if (disk.dev.how_probe == PROBE_FAILED) {
  247. printf("Not that many drives\n");
  248. return 0;
  249. }
  250. } while(disk.drive < drive);
  251. disk.direction = direction;
  252. disk.disk_offset = disk_offset;
  253. return disk_load(&disk.dev);
  254. }
  255. void disk_disable(void)
  256. {
  257. disable(&disk.dev);
  258. }
  259. #endif