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.

unhuf.S 9.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. /*****************************************************************************
  2. * NOTE: This code is no longer used in Etherboot. The obsolete
  3. * Makefile target .lzrom refers to it, but it is no longer being
  4. * maintained and may no longer work. Use .zrom instead (which uses
  5. * the unnrv2b decompressor).
  6. *****************************************************************************
  7. */
  8. /* At entry, the processor is in 16 bit real mode and the code is being
  9. * executed from an address it was not linked to. Code must be pic and
  10. * 32 bit sensitive until things are fixed up.
  11. */
  12. /* LZHuf (LZSS) Decompressing boot loader for ROM images
  13. *
  14. * this code is based on the work of Haruyasu Yoshizaki and Haruhiko Okumura
  15. * who implemented the original compressor and decompressor in C code
  16. *
  17. * Converted to 32bit assembly 16 July 2002 Eric Biederman <ebiederman@lnxi.com>
  18. * Made PIC 10 Aug 2002 Eric Biederman <ebiederman@lnxi.com>
  19. *
  20. * Copyright 1997 by M. Gutschke <gutschk@math.uni-muenster.de>
  21. *
  22. * Compression pays off, as soon as the uncompressed image is bigger than
  23. * about 1.5kB. This assumes an average compressibility of about 60%.
  24. */
  25. /* Do not change these values unless you really know what you are doing
  26. * the pre-computed lookup tables rely on the buffer size being 4kB or
  27. * smaller. The buffer size must be a power of two. The lookahead size has
  28. * to fit into 6 bits. If you change any of these numbers, you will also
  29. * have to adjust the compressor accordingly.
  30. */
  31. #define BUFSZ 4096
  32. #define LOOKAHEAD 60
  33. #define THRESHOLD 2
  34. #define NCHAR (256+LOOKAHEAD-THRESHOLD)
  35. #define TABLESZ (NCHAR+NCHAR-1)
  36. #define ROOT (TABLESZ-1)
  37. .text
  38. .arch i386
  39. .globl _start
  40. _start:
  41. cli
  42. /* Save the initial register values */
  43. pushal
  44. /*
  45. * See where I am running, and compute %ebp
  46. */
  47. call 1f
  48. 1: pop %ebp
  49. subl $1b, %ebp
  50. /*
  51. * INIT -- initializes all data structures
  52. * ====
  53. */
  54. init:
  55. cld
  56. leal dcodrle(%ebp), %esi /* uncompress run length encoded */
  57. leal dcode(%ebp), %edi /* lookup table for codes */
  58. movb $6, %dl
  59. movb $0x20, %dh
  60. xorb %bh,%bh
  61. init0:
  62. lodsb
  63. movb %al,%bl
  64. init1:
  65. xorl %ecx, %ecx
  66. movb %dh,%cl
  67. movb %bh,%al
  68. rep
  69. stosb
  70. incb %bh
  71. decb %bl
  72. jnz init1
  73. shrb %dh
  74. decb %dl
  75. jnz init0
  76. movb $1, %bl /* uncompress run length encoded */
  77. movb $6, %bh /* lookup table for code lengths */
  78. init2:
  79. lodsb
  80. xorl %ecx, %ecx
  81. movb %al,%cl
  82. movb %bl,%al
  83. rep
  84. stosb
  85. incb %bl
  86. decb %bh
  87. jnz init2
  88. movl $NCHAR, %ecx /* set all frequencies of leaf nodes */
  89. movw $1, %ax /* to one */
  90. rep
  91. stosw
  92. leal freq(%ebp), %esi
  93. movl $ROOT+1-NCHAR, %ecx
  94. init3:
  95. lodsw /* update frequencies of non-leaf nodes */
  96. movw %ax,%bx
  97. lodsw
  98. addw %bx,%ax
  99. stosw
  100. loop init3
  101. movw $0xFFFF, %ax
  102. stosw /* sentinel with infinite frequency */
  103. movl $NCHAR, %ecx
  104. movw $TABLESZ, %ax
  105. init4:
  106. stosw /* update son pointers for leaf nodes */
  107. incw %ax
  108. loop init4
  109. movl $ROOT+1-NCHAR, %ecx
  110. xorw %ax,%ax
  111. init5:
  112. stosw /* update son ptrs for non-leaf nodes */
  113. addw $2, %ax
  114. loop init5
  115. movl $ROOT+1-NCHAR, %ecx
  116. movw $NCHAR, %ax
  117. init6:
  118. stosw /* update parent ptrs for non-leaf nd. */
  119. stosw
  120. incw %ax
  121. loop init6
  122. movl $NCHAR, %ecx
  123. xorw %ax,%ax
  124. stosw /* root node has no parent */
  125. init7:
  126. stosw /* update parent ptrs for leaf nodes */
  127. incw %ax
  128. loop init7
  129. xorw %ax,%ax
  130. stosb /* clear getlen */
  131. stosw /* clear getbuf */
  132. movb $0x20, %al /* fill text buffer with spaces */
  133. leal spaces(%ebp), %edi
  134. movl $BUFSZ-LOOKAHEAD, %ecx
  135. rep
  136. stosb
  137. /* fall thru */
  138. /*
  139. * MAIN -- reads compressed codes and writes decompressed data
  140. * ====
  141. */
  142. leal _payload(%ebp), %esi /* get length of compressed data stream */
  143. leal uncompressed(%ebp), %edi
  144. lodsl
  145. movl %eax, %ecx
  146. main1:
  147. pushl %ecx
  148. call dcdchr /* decode one code symbol */
  149. orb %ah,%ah /* test if 8bit character */
  150. jnz main2
  151. stosb /* store verbatim */
  152. popl %ecx
  153. loop main1 /* proceed with next compressed code */
  154. jmp done /* until end of input is detected */
  155. main2:
  156. pushl %eax
  157. call dcdpos /* compute position in output buffer */
  158. movl %esi, %eax
  159. subl %edi, %ebx
  160. notl %ebx
  161. movl %ebx, %esi /* si := di - dcdpos() - 1 */
  162. popl %ecx
  163. subl $255-THRESHOLD, %ecx /* compute length of code sequence */
  164. movl %ecx, %edx
  165. rep
  166. movsb
  167. movl %eax,%esi
  168. popl %ecx
  169. subl %edx, %ecx /* check end of input condition */
  170. jnz main1 /* proceed with next compressed code */
  171. done:
  172. /* Start Etherboot */
  173. popal
  174. jmp uncompressed
  175. /*
  176. * GETBIT -- gets one bit pointed to by DS:ESI
  177. * ======
  178. *
  179. * changes: AX,CX,DL
  180. */
  181. getbit:
  182. movb $8, %cl
  183. movb getlen(%ebp), %dl /* compute number of bits required */
  184. subb %dl,%cl /* to fill read buffer */
  185. jae getbit1
  186. movw getbuf(%ebp), %ax /* there is still enough read ahead data */
  187. jmp getbit2
  188. getbit1:
  189. lodsb /* get next byte from input stream */
  190. xorb %ah,%ah
  191. shlw %cl,%ax /* shift, so that it will fit into */
  192. movw getbuf(%ebp), %cx /* read ahead buffer */
  193. orw %cx,%ax
  194. addb $8, %dl /* update number of bits in buffer */
  195. getbit2:
  196. movw %ax,%cx
  197. shlw %cx /* extract one bit from buffer */
  198. movw %cx, getbuf(%ebp)
  199. decb %dl
  200. movb %dl, getlen(%ebp) /* and update number of bits */
  201. shlw %ax /* return in carry flag */
  202. ret
  203. /*
  204. * DCDPOS -- decodes position in textbuffer as pointed to by DS:SI, result in BX
  205. * ======
  206. *
  207. * changes: AX,EBX,ECX,DX
  208. */
  209. dcdpos:
  210. movl $0x0800, %ebx
  211. dcdpos1:
  212. shlb %bl /* read one byte */
  213. call getbit
  214. jnc dcdpos2
  215. incb %bl
  216. dcdpos2:
  217. decb %bh
  218. jnz dcdpos1
  219. movb %bl,%dh /* read length of code from table */
  220. xorb %bh,%bh
  221. xorl %ecx, %ecx
  222. movb dlen(%ebx, %ebp),%cl
  223. movb dcode(%ebx, %ebp),%bl /* get top six bits from table */
  224. shll $6, %ebx
  225. dcdpos3:
  226. pushl %ecx /* read the rest from the input stream */
  227. shlb %dh
  228. call getbit
  229. jnc dcdpos4
  230. incb %dh
  231. dcdpos4:
  232. popl %ecx
  233. loop dcdpos3
  234. andb $0x3f, %dh /* combine upper and lower half of code */
  235. orb %dh,%bl
  236. ret
  237. /*
  238. * DCDCHR -- decodes one compressed character pointed to by DS:SI
  239. * ======
  240. *
  241. * changes: AX,BX,CX,DX
  242. */
  243. dcdchr:
  244. movl $ROOT, %ebx /* start at root entry */
  245. shll %ebx
  246. movzwl son(%ebx, %ebp),%ebx
  247. dcdchr1:
  248. call getbit /* get a single bit */
  249. jnc dcdchr2
  250. incl %ebx /* travel left or right */
  251. dcdchr2:
  252. shll %ebx
  253. movzwl son(%ebx, %ebp), %ebx
  254. cmpl $TABLESZ, %ebx /* until we come to a leaf node */
  255. jb dcdchr1
  256. movl %ebx, %eax
  257. subl $TABLESZ, %eax
  258. /* fall thru */
  259. /*
  260. * UPDATE -- updates huffman tree after incrementing frequency for code in BX
  261. * ======
  262. *
  263. * changes: BX,CX,DX
  264. */
  265. update:
  266. /* we do not check whether the frequency count has overrun.
  267. * this will cause problems for large files, but be should be fine
  268. * as long as the compressed size does not exceed 32kB and we
  269. * cannot do more than this anyways, because we load into the
  270. * upper 32kB of conventional memory
  271. */
  272. pushl %esi
  273. pushl %eax
  274. shll %ebx
  275. movzwl parent(%ebx, %ebp),%ebx
  276. update1:
  277. shll %ebx
  278. movzwl freq(%ebx, %ebp), %edx
  279. incl %edx /* increment frequency count by one */
  280. movw %dx, freq(%ebx, %ebp)
  281. leal 2+freq(%ebx, %ebp), %esi
  282. lodsw /* check if nodes need reordering */
  283. cmpw %ax, %dx
  284. jbe update5
  285. update2:
  286. lodsw
  287. cmpw %dx, %ax
  288. jb update2
  289. movzwl -4(%esi), %ecx
  290. movw %cx, freq(%ebx, %ebp) /* swap frequency of entries */
  291. movw %dx, -4(%esi)
  292. movl %esi, %eax /* compute index of new entry */
  293. subl $freq+4, %eax
  294. subl %ebp, %eax
  295. movl %eax, %edx
  296. shrl %eax
  297. movzwl son(%ebx, %ebp), %ecx /* get son of old entry */
  298. movl %ecx, %esi
  299. addl %esi, %esi
  300. movw %ax, parent(%esi, %ebp) /* and update the ptr to new parent */
  301. cmpl $TABLESZ, %ecx
  302. jae update3 /* do this for both branches */
  303. movw %ax, parent+2(%esi, %ebp) /* if not a leaf node */
  304. update3:
  305. movl %edx, %esi
  306. movzwl son(%esi, %ebp), %edx /* get son of new entry */
  307. movw %cx, son(%esi, %ebp) /* update its contents */
  308. movl %edx, %esi
  309. addl %esi, %esi
  310. movl %ebx, %ecx
  311. shrl %ecx
  312. movw %cx, parent(%esi, %ebp) /* and update the ptr to new paren */
  313. cmpl $TABLESZ, %edx
  314. jae update4 /* do this for both branches */
  315. movw %cx, parent+2(%esi, %ebp) /* if not a leaf node */
  316. update4:
  317. movw %dx, son(%ebx, %ebp) /* update son of old entry */
  318. movl %eax, %ebx /* continue with new entry */
  319. shll %ebx
  320. update5:
  321. movzwl parent(%ebx, %ebp), %ebx /* continue with parent */
  322. orl %ebx, %ebx
  323. jnz update1 /* until we found the root entry */
  324. popl %eax
  325. popl %esi
  326. ret
  327. /*
  328. * constant data. this part of the program resides in ROM and cannot be
  329. * changed
  330. *
  331. * run length encoded tables will be uncompressed into the bss segment
  332. * take care with any symbols here for .com files to add 0x100 to address
  333. */
  334. dcodrle: .byte 0x01,0x03,0x08,0x0C,0x18,0x10
  335. dlenrle: .byte 0x20,0x30,0x40,0x30,0x30,0x10
  336. /*
  337. * variable data segment (bss)
  338. * this segment will always be found at 0x90000 (i.e. at RELOC - SCRATCH)
  339. *
  340. * do not change the order or the sizes of any of the following tables
  341. * the initialization code makes assumptions on the exact layout of the
  342. * data structures...
  343. */
  344. .bss
  345. /* lookup table for index into buffer of recently output characters */
  346. dcode: .skip 256
  347. /* lookup table for length of code sequence from buffer of recent characters */
  348. dlen: .skip 256
  349. /* table with frequency counts for all codes */
  350. freq: .skip 2*(TABLESZ+1)
  351. /* pointer to child nodes */
  352. son: .skip 2*(TABLESZ)
  353. /* the first part of this table contains all the codes (0..TABLESZ-1) */
  354. /* the second part contains all leaf nodes (TABLESZ..) */
  355. parent: .skip 2*(TABLESZ+NCHAR)
  356. /* temporary storage for extracting bits from compressed data stream */
  357. getlen: .skip 1
  358. getbuf: .skip 1
  359. /* the initial buffer has to be filled with spaces */
  360. .balign 4
  361. spaces:
  362. .skip BUFSZ - LOOKAHEAD
  363. /* uncompressed data will be written here */
  364. uncompressed: