misc.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:10k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * misc.c
  3.  * 
  4.  * This is a collection of several routines from gzip-1.0.3 
  5.  * adapted for Linux.
  6.  *
  7.  * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
  8.  * puts by Nick Holloway 1993, better puts by Martin Mares 1995
  9.  * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
  10.  */
  11. #include "miscsetup.h"
  12. #include <asm/io.h>
  13. /*
  14.  * gzip declarations
  15.  */
  16. #define OF(args)  args
  17. #define STATIC static
  18. #undef memset
  19. #undef memcpy
  20. #define memzero(s, n)     memset ((s), 0, (n))
  21. typedef unsigned char  uch;
  22. typedef unsigned short ush;
  23. typedef unsigned long  ulg;
  24. #define WSIZE 0x8000 /* Window size must be at least 32k, */
  25. /* and a power of two */
  26. static uch *inbuf;      /* input buffer */
  27. static uch window[WSIZE];    /* Sliding window buffer */
  28. static unsigned insize = 0;  /* valid bytes in inbuf */
  29. static unsigned inptr = 0;   /* index of next byte to be processed in inbuf */
  30. static unsigned outcnt = 0;  /* bytes in output buffer */
  31. /* gzip flag byte */
  32. #define ASCII_FLAG   0x01 /* bit 0 set: file probably ASCII text */
  33. #define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
  34. #define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
  35. #define ORIG_NAME    0x08 /* bit 3 set: original file name present */
  36. #define COMMENT      0x10 /* bit 4 set: file comment present */
  37. #define ENCRYPTED    0x20 /* bit 5 set: file is encrypted */
  38. #define RESERVED     0xC0 /* bit 6,7:   reserved */
  39. #define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf())
  40. /* Diagnostic functions */
  41. #ifdef DEBUG
  42. #  define Assert(cond,msg) {if(!(cond)) error(msg);}
  43. #  define Trace(x) fprintf x
  44. #  define Tracev(x) {if (verbose) fprintf x ;}
  45. #  define Tracevv(x) {if (verbose>1) fprintf x ;}
  46. #  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
  47. #  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
  48. #else
  49. #  define Assert(cond,msg)
  50. #  define Trace(x)
  51. #  define Tracev(x)
  52. #  define Tracevv(x)
  53. #  define Tracec(c,x)
  54. #  define Tracecv(c,x)
  55. #endif
  56. static int  fill_inbuf(void);
  57. static void flush_window(void);
  58. static void error(char *m);
  59. static void gzip_mark(void **);
  60. static void gzip_release(void **);
  61.   
  62. /*
  63.  * This is set up by the setup-routine at boot-time
  64.  */
  65. static unsigned char *real_mode; /* Pointer to real-mode data */
  66. #define EXT_MEM_K   (*(unsigned short *)(real_mode + 0x2))
  67. #ifndef STANDARD_MEMORY_BIOS_CALL
  68. #define ALT_MEM_K   (*(unsigned long *)(real_mode + 0x1e0))
  69. #endif
  70. #define SCREEN_INFO (*(struct screen_info *)(real_mode+0))
  71. extern char input_data[];
  72. extern int input_len;
  73. static long bytes_out = 0;
  74. static uch *output_data;
  75. static unsigned long output_ptr = 0;
  76.  
  77. static void *malloc(int size);
  78. static void free(void *where);
  79. static void error(char *m);
  80. static void gzip_mark(void **);
  81. static void gzip_release(void **);
  82.  
  83. static void puts(const char *);
  84.   
  85. extern int end;
  86. static long free_mem_ptr = (long)&end;
  87. static long free_mem_end_ptr;
  88. #define INPLACE_MOVE_ROUTINE  0x1000
  89. #define LOW_BUFFER_START      0x2000
  90. #define LOW_BUFFER_MAX       0x90000
  91. #define HEAP_SIZE             0x3000
  92. static unsigned int low_buffer_end, low_buffer_size;
  93. static int high_loaded =0;
  94. static uch *high_buffer_start /* = (uch *)(((ulg)&end) + HEAP_SIZE)*/;
  95. static char *vidmem = (char *)0xb8000;
  96. static int vidport;
  97. static int lines, cols;
  98. #include "../../../../lib/inflate.c"
  99. static void *malloc(int size)
  100. {
  101. void *p;
  102. if (size <0) error("Malloc errorn");
  103. if (free_mem_ptr <= 0) error("Memory errorn");
  104. free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
  105. p = (void *)free_mem_ptr;
  106. free_mem_ptr += size;
  107. if (free_mem_ptr >= free_mem_end_ptr)
  108. error("nOut of memoryn");
  109. return p;
  110. }
  111. static void free(void *where)
  112. { /* Don't care */
  113. }
  114. static void gzip_mark(void **ptr)
  115. {
  116. *ptr = (void *) free_mem_ptr;
  117. }
  118. static void gzip_release(void **ptr)
  119. {
  120. free_mem_ptr = (long) *ptr;
  121. }
  122.  
  123. static void scroll(void)
  124. {
  125. int i;
  126. memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 );
  127. for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 )
  128. vidmem[i] = ' ';
  129. }
  130. static void puts(const char *s)
  131. {
  132. int x,y,pos;
  133. char c;
  134. x = SCREEN_INFO.orig_x;
  135. y = SCREEN_INFO.orig_y;
  136. while ( ( c = *s++ ) != '' ) {
  137. if ( c == 'n' ) {
  138. x = 0;
  139. if ( ++y >= lines ) {
  140. scroll();
  141. y--;
  142. }
  143. } else {
  144. vidmem [ ( x + cols * y ) * 2 ] = c; 
  145. if ( ++x >= cols ) {
  146. x = 0;
  147. if ( ++y >= lines ) {
  148. scroll();
  149. y--;
  150. }
  151. }
  152. }
  153. }
  154. SCREEN_INFO.orig_x = x;
  155. SCREEN_INFO.orig_y = y;
  156. pos = (x + cols * y) * 2; /* Update cursor position */
  157. outb_p(14, vidport);
  158. outb_p(0xff & (pos >> 9), vidport+1);
  159. outb_p(15, vidport);
  160. outb_p(0xff & (pos >> 1), vidport+1);
  161. }
  162. void* memset(void* s, int c, size_t n)
  163. {
  164. int i;
  165. char *ss = (char*)s;
  166. for (i=0;i<n;i++) ss[i] = c;
  167. return s;
  168. }
  169. void* memcpy(void* __dest, __const void* __src,
  170.     size_t __n)
  171. {
  172. int i;
  173. char *d = (char *)__dest, *s = (char *)__src;
  174. for (i=0;i<__n;i++) d[i] = s[i];
  175. return __dest;
  176. }
  177. /* ===========================================================================
  178.  * Fill the input buffer. This is called only when the buffer is empty
  179.  * and at least one byte is really needed.
  180.  */
  181. static int fill_inbuf(void)
  182. {
  183. if (insize != 0) {
  184. error("ran out of input datan");
  185. }
  186. inbuf = input_data;
  187. insize = input_len;
  188. inptr = 1;
  189. return inbuf[0];
  190. }
  191. /* ===========================================================================
  192.  * Write the output window window[0..outcnt-1] and update crc and bytes_out.
  193.  * (Used for the decompressed data only.)
  194.  */
  195. static void flush_window_low(void)
  196. {
  197.     ulg c = crc;         /* temporary variable */
  198.     unsigned n;
  199.     uch *in, *out, ch;
  200.     
  201.     in = window;
  202.     out = &output_data[output_ptr]; 
  203.     for (n = 0; n < outcnt; n++) {
  204.     ch = *out++ = *in++;
  205.     c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
  206.     }
  207.     crc = c;
  208.     bytes_out += (ulg)outcnt;
  209.     output_ptr += (ulg)outcnt;
  210.     outcnt = 0;
  211. }
  212. static void flush_window_high(void)
  213. {
  214.     ulg c = crc;         /* temporary variable */
  215.     unsigned n;
  216.     uch *in,  ch;
  217.     in = window;
  218.     for (n = 0; n < outcnt; n++) {
  219. ch = *output_data++ = *in++;
  220. if ((ulg)output_data == low_buffer_end) output_data=high_buffer_start;
  221. c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
  222.     }
  223.     crc = c;
  224.     bytes_out += (ulg)outcnt;
  225.     outcnt = 0;
  226. }
  227. static void flush_window(void)
  228. {
  229. if (high_loaded) flush_window_high();
  230. else flush_window_low();
  231. }
  232. static void error(char *x)
  233. {
  234. puts("nn");
  235. puts(x);
  236. puts("nn -- System halted");
  237. while(1); /* Halt */
  238. }
  239. void setup_normal_output_buffer(void)
  240. {
  241. #ifdef STANDARD_MEMORY_BIOS_CALL
  242. if (EXT_MEM_K < 1024) error("Less than 2MB of memory.n");
  243. #else
  244. if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < 1024) error("Less than 2MB of memory.n");
  245. #endif
  246. output_data = (char *)0x100000; /* Points to 1M */
  247. free_mem_end_ptr = (long)real_mode;
  248. }
  249. struct moveparams {
  250. uch *low_buffer_start;  int lcount;
  251. uch *high_buffer_start; int hcount;
  252. };
  253. void setup_output_buffer_if_we_run_high(struct moveparams *mv)
  254. {
  255. high_buffer_start = (uch *)(((ulg)&end) + HEAP_SIZE);
  256. #ifdef STANDARD_MEMORY_BIOS_CALL
  257. if (EXT_MEM_K < (3*1024)) error("Less than 4MB of memory.n");
  258. #else
  259. if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < (3*1024)) error("Less than 4MB of memory.n");
  260. #endif
  261. mv->low_buffer_start = output_data = (char *)LOW_BUFFER_START;
  262. low_buffer_end = ((unsigned int)real_mode > LOW_BUFFER_MAX
  263.   ? LOW_BUFFER_MAX : (unsigned int)real_mode) & ~0xfff;
  264. low_buffer_size = low_buffer_end - LOW_BUFFER_START;
  265. high_loaded = 1;
  266. free_mem_end_ptr = (long)high_buffer_start;
  267. if ( (0x100000 + low_buffer_size) > ((ulg)high_buffer_start)) {
  268. high_buffer_start = (uch *)(0x100000 + low_buffer_size);
  269. mv->hcount = 0; /* say: we need not to move high_buffer */
  270. }
  271. else mv->hcount = -1;
  272. mv->high_buffer_start = high_buffer_start;
  273. }
  274. void close_output_buffer_if_we_run_high(struct moveparams *mv)
  275. {
  276. if (bytes_out > low_buffer_size) {
  277. mv->lcount = low_buffer_size;
  278. if (mv->hcount)
  279. mv->hcount = bytes_out - low_buffer_size;
  280. } else {
  281. mv->lcount = bytes_out;
  282. mv->hcount = 0;
  283. }
  284. }
  285. void check_cpu(void)
  286. {
  287. int res = 0;
  288. asm volatile( " n
  289. movl $3,%%edx # at least 386 n
  290. pushfl # push EFLAGS n
  291. popl %%eax # get EFLAGS n
  292. movl %%eax,%%ecx # save original EFLAGS n
  293. xorl $0x40000,%%eax # flip AC bit in EFLAGS n
  294. pushl %%eax # copy to EFLAGS n
  295. popfl # set EFLAGS n
  296. pushfl # get new EFLAGS n
  297. popl %%eax # put it in eax n
  298. xorl %%ecx,%%eax # change in flags n
  299. andl $0x40000,%%eax # check if AC bit changed n
  300. je 1f n
  301. n
  302. movl $4,%%edx # at least 486 n
  303. movl %%ecx,%%eax n
  304. xorl $0x200000,%%eax # check ID flag n
  305. pushl %%eax n
  306. popfl # if we are on a straight 486DX, SX, or n
  307. pushfl # 487SX we can't change it n
  308. popl %%eax n
  309. xorl %%ecx,%%eax n
  310. pushl %%ecx # restore original EFLAGS n
  311. popfl n
  312. andl $0x200000,%%eax n
  313. je 1f n
  314. n
  315. /* get vendor info */ n
  316. # xorl %%eax,%%eax # call CPUID with 0 -> return vendor ID n
  317. # cpuid n
  318. # movl $5, %%edx n
  319. # cmpl $0x41757468,%%ebx # check thats amd n
  320. # jne 1f n
  321. n
  322. mov $0x80000000,%%eax # Is extended cpuid supported?n
  323. cpuidn
  324. test $0x80000000,%%eaxn
  325. movl $5, %%edx n
  326. jz 1fn
  327. n
  328. movl $0x80000001,%%eax n
  329. cpuid n
  330. andl $0x20000000,%%edx n
  331. movl $6, %%edx n
  332. jz 1f n
  333. n
  334. movl $7, %%edx n
  335. 1:" : "=d" (res) : : "eax", "ebx", "ecx" );
  336. switch (res) {
  337. case 3: puts( "386" );
  338. break;
  339. case 4: puts( "486" );
  340. break;
  341. case 5: puts( "no extended cpuid" );
  342. break;
  343. case 6: puts( "non-64bit 586+" );
  344. break;
  345. case 7: puts( "64bit" );
  346. break;
  347. default:puts( "internal error" );
  348. break;
  349. }
  350. if (res !=7)
  351. error( "Sorry, your CPU is not capable of running 64-bit kernel." );
  352. }
  353. int decompress_kernel(struct moveparams *mv, void *rmode)
  354. {
  355. real_mode = rmode;
  356. if (SCREEN_INFO.orig_video_mode == 7) {
  357. vidmem = (char *) 0xb0000;
  358. vidport = 0x3b4;
  359. } else {
  360. vidmem = (char *) 0xb8000;
  361. vidport = 0x3d4;
  362. }
  363. lines = SCREEN_INFO.orig_video_lines;
  364. cols = SCREEN_INFO.orig_video_cols;
  365. if (free_mem_ptr < 0x100000) setup_normal_output_buffer();
  366. else setup_output_buffer_if_we_run_high(mv);
  367. makecrc();
  368. puts("Checking CPU type...");
  369. check_cpu();
  370. puts(".nDecompressing Linux...");
  371. gunzip();
  372. puts("done.nBooting the kernel.n");
  373. if (high_loaded) close_output_buffer_if_we_run_high(mv);
  374. return high_loaded;
  375. }