Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

dskprefix.S 8.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. /* NOTE: this boot sector contains instructions that need at least an 80186.
  2. * Yes, as86 has a bug somewhere in the valid instruction set checks.
  3. *
  4. */
  5. /* floppyload.S Copyright (C) 1991, 1992 Linus Torvalds
  6. * modified by Drew Eckhardt
  7. * modified by Bruce Evans (bde)
  8. *
  9. * floppyprefix.S is loaded at 0x0000:0x7c00 by the bios-startup routines.
  10. *
  11. * It then loads the system at SYSSEG<<4, using BIOS interrupts.
  12. *
  13. * The loader has been made as simple as possible, and continuous read errors
  14. * will result in a unbreakable loop. Reboot by hand. It loads pretty fast by
  15. * getting whole tracks at a time whenever possible.
  16. */
  17. FILE_LICENCE ( GPL2_ONLY )
  18. #include <librm.h>
  19. .equ BOOTSEG, 0x07C0 /* original address of boot-sector */
  20. .equ SYSSEG, 0x1000 /* system loaded at SYSSEG<<4 */
  21. .org 0
  22. .arch i386
  23. .text
  24. .section ".prefix", "ax", @progbits
  25. .code16
  26. .globl _dsk_start
  27. _dsk_start:
  28. jmp $BOOTSEG, $go /* reload cs:ip to match relocation addr */
  29. go:
  30. movw $0x2000-12, %di /* 0x2000 is arbitrary value >= length */
  31. /* of bootsect + room for stack + 12 for */
  32. /* saved disk parm block */
  33. movw $BOOTSEG, %ax
  34. movw %ax,%ds
  35. movw %ax,%es
  36. movw %ax,%ss /* put stack at BOOTSEG:0x4000-12. */
  37. movw %di,%sp
  38. /* Many BIOS's default disk parameter tables will not recognize multi-sector
  39. * reads beyond the maximum sector number specified in the default diskette
  40. * parameter tables - this may mean 7 sectors in some cases.
  41. *
  42. * Since single sector reads are slow and out of the question, we must take care
  43. * of this by creating new parameter tables (for the first disk) in RAM. We
  44. * will set the maximum sector count to 36 - the most we will encounter on an
  45. * ED 2.88. High doesn't hurt. Low does.
  46. *
  47. * Segments are as follows: ds=es=ss=cs - BOOTSEG
  48. */
  49. xorw %cx,%cx
  50. movw %cx,%es /* access segment 0 */
  51. movw $0x78, %bx /* 0:bx is parameter table address */
  52. pushw %ds /* save ds */
  53. /* 0:bx is parameter table address */
  54. ldsw %es:(%bx),%si /* loads ds and si */
  55. movw %ax,%es /* ax is BOOTSECT (loaded above) */
  56. movb $6, %cl /* copy 12 bytes */
  57. cld
  58. pushw %di /* keep a copy for later */
  59. rep
  60. movsw /* ds:si is source, es:di is dest */
  61. popw %di
  62. movb $36,%es:4(%di)
  63. movw %cx,%ds /* access segment 0 */
  64. xchgw %di,(%bx)
  65. movw %es,%si
  66. xchgw %si,2(%bx)
  67. popw %ds /* restore ds */
  68. movw %di, dpoff /* save old parameters */
  69. movw %si, dpseg /* to restore just before finishing */
  70. pushw %ds
  71. popw %es /* reload es */
  72. /* Note that es is already set up. Also cx is 0 from rep movsw above. */
  73. xorb %ah,%ah /* reset FDC */
  74. xorb %dl,%dl
  75. int $0x13
  76. /* Get disk drive parameters, specifically number of sectors/track.
  77. *
  78. * It seems that there is no BIOS call to get the number of sectors. Guess
  79. * 36 sectors if sector 36 can be read, 18 sectors if sector 18 can be read,
  80. * 15 if sector 15 can be read. Otherwise guess 9.
  81. */
  82. movw $disksizes, %si /* table of sizes to try */
  83. probe_loop:
  84. lodsb
  85. cbtw /* extend to word */
  86. movw %ax, sectors
  87. cmpw $disksizes+4, %si
  88. jae got_sectors /* if all else fails, try 9 */
  89. xchgw %cx,%ax /* cx = track and sector */
  90. xorw %dx,%dx /* drive 0, head 0 */
  91. movw $0x0200, %bx /* address after boot sector */
  92. /* (512 bytes from origin, es = cs) */
  93. movw $0x0201, %ax /* service 2, 1 sector */
  94. int $0x13
  95. jc probe_loop /* try next value */
  96. got_sectors:
  97. movw $msg1end-msg1, %cx
  98. movw $msg1, %si
  99. call print_str
  100. /* ok, we've written the Loading... message, now we want to load the system */
  101. movw $SYSSEG, %ax
  102. movw %ax,%es /* segment of SYSSEG<<4 */
  103. pushw %es
  104. call read_it
  105. /* This turns off the floppy drive motor, so that we enter the kernel in a
  106. * known state, and don't have to worry about it later.
  107. */
  108. movw $0x3f2, %dx
  109. xorb %al,%al
  110. outb %al,%dx
  111. call print_nl
  112. pop %es /* = SYSSEG */
  113. /* Restore original disk parameters */
  114. movw $0x78, %bx
  115. movw dpoff, %di
  116. movw dpseg, %si
  117. xorw %ax,%ax
  118. movw %ax,%ds
  119. movw %di,(%bx)
  120. movw %si,2(%bx)
  121. /* Everything now loaded. %es = SYSSEG, so %es:0000 points to
  122. * start of loaded image.
  123. */
  124. /* Jump to loaded copy */
  125. ljmp $SYSSEG, $start_runtime
  126. endseg: .word SYSSEG
  127. .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
  128. .ascii "ADDW"
  129. .long endseg
  130. .long 16
  131. .long 0
  132. .previous
  133. /* This routine loads the system at address SYSSEG<<4, making sure no 64kB
  134. * boundaries are crossed. We try to load it as fast as possible, loading whole
  135. * tracks whenever we can.
  136. *
  137. * in: es - starting address segment (normally SYSSEG)
  138. */
  139. read_it:
  140. movw $0,sread /* load whole image including prefix */
  141. movw %es,%ax
  142. testw $0x0fff, %ax
  143. die: jne die /* es must be at 64kB boundary */
  144. xorw %bx,%bx /* bx is starting address within segment */
  145. rp_read:
  146. movw %es,%ax
  147. movw %bx,%dx
  148. movb $4, %cl
  149. shrw %cl,%dx /* bx is always divisible by 16 */
  150. addw %dx,%ax
  151. cmpw endseg, %ax /* have we loaded all yet? */
  152. jb ok1_read
  153. ret
  154. ok1_read:
  155. movw sectors, %ax
  156. subw sread, %ax
  157. movw %ax,%cx
  158. shlw $9, %cx
  159. addw %bx,%cx
  160. jnc ok2_read
  161. je ok2_read
  162. xorw %ax,%ax
  163. subw %bx,%ax
  164. shrw $9, %ax
  165. ok2_read:
  166. call read_track
  167. movw %ax,%cx
  168. addw sread, %ax
  169. cmpw sectors, %ax
  170. jne ok3_read
  171. movw $1, %ax
  172. subw head, %ax
  173. jne ok4_read
  174. incw track
  175. ok4_read:
  176. movw %ax, head
  177. xorw %ax,%ax
  178. ok3_read:
  179. movw %ax, sread
  180. shlw $9, %cx
  181. addw %cx,%bx
  182. jnc rp_read
  183. movw %es,%ax
  184. addb $0x10, %ah
  185. movw %ax,%es
  186. xorw %bx,%bx
  187. jmp rp_read
  188. read_track:
  189. pusha
  190. pushw %ax
  191. pushw %bx
  192. pushw %bp /* just in case the BIOS is buggy */
  193. movw $0x0e2e, %ax /* 0x2e = . */
  194. movw $0x0007, %bx
  195. int $0x10
  196. popw %bp
  197. popw %bx
  198. popw %ax
  199. movw track, %dx
  200. movw sread, %cx
  201. incw %cx
  202. movb %dl,%ch
  203. movw head, %dx
  204. movb %dl,%dh
  205. andw $0x0100, %dx
  206. movb $2, %ah
  207. pushw %dx /* save for error dump */
  208. pushw %cx
  209. pushw %bx
  210. pushw %ax
  211. int $0x13
  212. jc bad_rt
  213. addw $8, %sp
  214. popa
  215. ret
  216. bad_rt: pushw %ax /* save error code */
  217. call print_all /* ah = error, al = read */
  218. xorb %ah,%ah
  219. xorb %dl,%dl
  220. int $0x13
  221. addw $10, %sp
  222. popa
  223. jmp read_track
  224. /* print_all is for debugging purposes. It will print out all of the registers.
  225. * The assumption is that this is called from a routine, with a stack frame like
  226. * dx
  227. * cx
  228. * bx
  229. * ax
  230. * error
  231. * ret <- sp
  232. */
  233. print_all:
  234. call print_nl /* nl for readability */
  235. movw $5, %cx /* error code + 4 registers */
  236. movw %sp,%bp
  237. print_loop:
  238. pushw %cx /* save count left */
  239. cmpb $5, %cl
  240. jae no_reg /* see if register name is needed */
  241. movw $0x0007, %bx /* page 0, attribute 7 (normal) */
  242. movw $0xe05+0x41-1, %ax
  243. subb %cl,%al
  244. int $0x10
  245. movb $0x58, %al /* 'X' */
  246. int $0x10
  247. movb $0x3A, %al /* ':' */
  248. int $0x10
  249. no_reg:
  250. addw $2, %bp /* next register */
  251. call print_hex /* print it */
  252. movb $0x20, %al /* print a space */
  253. int $0x10
  254. popw %cx
  255. loop print_loop
  256. call print_nl /* nl for readability */
  257. ret
  258. print_str:
  259. movw $0x0007, %bx /* page 0, attribute 7 (normal) */
  260. movb $0x0e, %ah /* write char, tty mode */
  261. prloop:
  262. lodsb
  263. int $0x10
  264. loop prloop
  265. ret
  266. print_nl:
  267. movw $0x0007, %bx /* page 0, attribute 7 (normal) */
  268. movw $0xe0d, %ax /* CR */
  269. int $0x10
  270. movb $0xa, %al /* LF */
  271. int $0x10
  272. ret
  273. /* print_hex prints the word pointed to by ss:bp in hexadecimal. */
  274. print_hex:
  275. movw (%bp),%dx /* load word into dx */
  276. movb $4, %cl
  277. movb $0x0e, %ah /* write char, tty mode */
  278. movw $0x0007, %bx /* page 0, attribute 7 (normal) */
  279. call print_digit
  280. call print_digit
  281. call print_digit
  282. /* fall through */
  283. print_digit:
  284. rol %cl,%dx /* rotate so that lowest 4 bits are used */
  285. movb $0x0f, %al /* mask for nybble */
  286. andb %dl,%al
  287. addb $0x90, %al /* convert al to ascii hex (four instructions) */
  288. daa
  289. adcb $0x40, %al
  290. daa
  291. int $0x10
  292. ret
  293. sread: .word 0 /* sectors read of current track */
  294. head: .word 0 /* current head */
  295. track: .word 0 /* current track */
  296. sectors:
  297. .word 0
  298. dpseg: .word 0
  299. dpoff: .word 0
  300. disksizes:
  301. .byte 36,18,15,9
  302. msg1:
  303. .ascii "Loading ROM image"
  304. msg1end:
  305. .org 510, 0
  306. .word 0xAA55
  307. start_runtime:
  308. /* Install iPXE */
  309. call install
  310. /* Set up real-mode stack */
  311. movw %bx, %ss
  312. movw $_estack16, %sp
  313. /* Jump to .text16 segment */
  314. pushw %ax
  315. pushw $1f
  316. lret
  317. .section ".text16", "awx", @progbits
  318. 1:
  319. /* Run iPXE */
  320. virtcall main
  321. /* Uninstall iPXE */
  322. call uninstall
  323. /* Boot next device */
  324. int $0x18