home *** CD-ROM | disk | FTP | other *** search
/ Boot Disc 15 / boot-disc-1997-11.iso / Debian / Tools / LODLIN16.ZIP / LODLIN16 / SRC / SRCLINUX / PGADJUST.C < prev   
C/C++ Source or Header  |  1996-03-16  |  8KB  |  369 lines

  1. /*
  2.  * padjust.c
  3.  * 
  4.  * partially stolen from linux/arch/i386/boot/compressed/misc.c
  5.  *
  6.  */
  7.  
  8. #ifdef STANDALONE_DEBUG
  9.   #include <stdio.h>
  10.   #include <stdlib.h>
  11. #endif
  12.  
  13.  
  14. #include <string.h>
  15. #include <asm/segment.h>
  16. #include <asm/io.h>
  17.  
  18. /*
  19.  * These are set up by the setup-routine at boot-time:
  20.  */
  21.  
  22. struct screen_info {
  23.     unsigned char  orig_x;
  24.     unsigned char  orig_y;
  25.     unsigned char  unused1[2];
  26.     unsigned short orig_video_page;
  27.     unsigned char  orig_video_mode;
  28.     unsigned char  orig_video_cols;
  29.     unsigned short unused2;
  30.     unsigned short orig_video_ega_bx;
  31.     unsigned short unused3;
  32.     unsigned char  orig_video_lines;
  33.     unsigned char  orig_video_isVGA;
  34. };
  35.  
  36. /*
  37.  * This is set up by the setup-routine at boot-time
  38.  */
  39. #define EXT_MEM_K (*(unsigned short *)0x90002)
  40. #define DRIVE_INFO (*(struct drive_info *)0x90080)
  41. #define SCREEN_INFO (*(struct screen_info *)0x90000)
  42. #define RAMDISK_SIZE (*(unsigned short *)0x901F8)
  43. #define ORIG_ROOT_DEV (*(unsigned short *)0x901FC)
  44. #define AUX_DEVICE_INFO (*(unsigned char *)0x901FF)
  45.  
  46. /* --------------------------------------------------------------------- */
  47.  
  48. /*
  49.  * This (also set up by the setup-routine) is our special extension
  50.  * Here we have all params we got from 16-bit LOADLIN
  51.  */
  52.  
  53. struct pblock {
  54.   unsigned long taddr;    /* linear address where the block of pages
  55.                              must be moved to */
  56.   unsigned short start;   /* index within sources of first entry */
  57.   unsigned short tcount;  /* number of entries for taddr in sources */
  58. };
  59.  
  60. struct source_entry {
  61.   unsigned long usedby:12;
  62.   unsigned long pagenum:20;
  63.   #define IS_UNUSED  0xfff
  64.   #define IS_MOVED   0xffe
  65. };
  66.  
  67. struct pages_list {
  68.   unsigned long count;     /* number of entries in 'sources' */
  69.   long number_of_blocks;   /* number of valid blocks-items */
  70.   void *auxbuf;            /* address of 4096 bytes auxiliary buffer */
  71.   struct pblock blocks[4];
  72.   struct source_entry sources[1]; /* list of addresses where the block of pages
  73.                               currently _is_ located */
  74. };
  75.  
  76. #ifndef STANDALONE_DEBUG
  77. #define PAGELIST     (*(struct pages_list **)0x94008)
  78. #else
  79.   struct pages_list *PAGELIST=0;
  80. #endif
  81.  
  82. #define S PAGELIST->sources
  83. #define REAL_STARTUP_32  ( *((unsigned long *)0x9400C) )
  84.  
  85. /* --------------------------------------------------------------------- */
  86.  
  87.  
  88. static void error(char *m);
  89.  
  90. #ifndef STANDALONE_DEBUG
  91. static void puts(const char *);
  92.   
  93. static char *vidmem = (char *)0xb8000;
  94. static int vidport;
  95. static int lines, cols;
  96.  
  97. static void scroll()
  98. {
  99.     int i;
  100.  
  101.     memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 );
  102.     for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 )
  103.         vidmem[i] = ' ';
  104. }
  105.  
  106. static void puts(const char *s)
  107. {
  108.     int x,y,pos;
  109.     char c;
  110.  
  111.     x = SCREEN_INFO.orig_x;
  112.     y = SCREEN_INFO.orig_y;
  113.  
  114.     while ( ( c = *s++ ) != '\0' ) {
  115.         if ( c == '\n' ) {
  116.             x = 0;
  117.             if ( ++y >= lines ) {
  118.                 scroll();
  119.                 y--;
  120.             }
  121.         } else {
  122.             vidmem [ ( x + cols * y ) * 2 ] = c; 
  123.             if ( ++x >= cols ) {
  124.                 x = 0;
  125.                 if ( ++y >= lines ) {
  126.                     scroll();
  127.                     y--;
  128.                 }
  129.             }
  130.         }
  131.     }
  132.  
  133.     SCREEN_INFO.orig_x = x;
  134.     SCREEN_INFO.orig_y = y;
  135.  
  136.     pos = (x + cols * y) * 2;    /* Update cursor position */
  137.     outb_p(14, vidport);
  138.     outb_p(0xff & (pos >> 9), vidport+1);
  139.     outb_p(15, vidport);
  140.     outb_p(0xff & (pos >> 1), vidport+1);
  141. }
  142.  
  143. __ptr_t memset(__ptr_t s, int c, size_t n)
  144. {
  145.     int i;
  146.     char *ss = (char*)s;
  147.  
  148.     for (i=0;i<n;i++) ss[i] = c;
  149. }
  150.  
  151. __ptr_t memcpy(__ptr_t __dest, __const __ptr_t __src,
  152.                 size_t __n)
  153. {
  154.     int i;
  155.     char *d = (char *)__dest, *s = (char *)__src;
  156.  
  157.     for (i=0;i<__n;i++) d[i] = s[i];
  158. }
  159. #endif
  160.  
  161. void put_hex(unsigned long v)
  162. {
  163.   static char table[17]="0123456789ABCDEF";
  164.   char b[9];
  165.   int i;
  166.   for (i=7; i >=0; i--) {
  167.     b[i] = table[v & 15];
  168.     v >>=4;
  169.   }
  170.   b[8]=0;
  171.   puts(b);
  172. }
  173.  
  174.  
  175. static void error(char *x)
  176. {
  177.     puts("\n\n");
  178.     puts(x);
  179.     puts("\n\n -- System halted");
  180.  
  181.     while(1);    /* Halt */
  182. }
  183.  
  184. #ifdef STANDALONE_DEBUG
  185. static void memcpy_page(void *t,void *s)
  186. {
  187.   printf("%p = %p\n",t,s);
  188. }
  189. #else
  190. static void memcpy_page(void *t,void *s)
  191. {
  192.   memcpy(t,s,4096);
  193. }
  194. #endif
  195.  
  196. static int index_within_sources(unsigned long pgnum)
  197. {
  198.   int i;
  199.   for (i=0; i< PAGELIST->number_of_blocks; i++) {
  200.     unsigned long pstart=(PAGELIST->blocks[i].taddr >> 12);
  201.     unsigned long pstop= pstart + PAGELIST->blocks[i].tcount;
  202.     if ((pgnum >= pstart) && (pgnum < pstop)) {
  203.       return (pgnum - pstart) + PAGELIST->blocks[i].start;
  204.     }
  205.   }
  206.   return IS_UNUSED;
  207. }
  208.  
  209. static void * address_of_target(int sindex)
  210. {
  211.   int i, j=0;
  212.   for (i=0; i < PAGELIST->number_of_blocks; i++) {
  213.     j += PAGELIST->blocks[i].tcount;
  214.     if (sindex < j) {
  215.       return (void *)(((PAGELIST->blocks[i].taddr >> 12) + (sindex - PAGELIST->blocks[i].start)) << 12);
  216.     }
  217.   }
  218.   return 0; /* invalid */
  219. }
  220.  
  221.  
  222. static void build_references(void)
  223. {
  224.   int i,j;
  225.   for (i=0; i < PAGELIST->count; i++) {
  226.     S[i].usedby = IS_UNUSED;
  227.   }
  228.   for (i=0; i < PAGELIST->count; i++) {
  229.     j= index_within_sources(S[i].pagenum);
  230.     if ( j != IS_UNUSED ) {
  231.       if (j == i) S[i].usedby = IS_MOVED;
  232.       else S[j].usedby = i;
  233.     }
  234.   }
  235. }
  236.  
  237. static int recursion_start_index=0;
  238.  
  239.  
  240. #ifdef VERBOSE
  241. static printmove(int sindex)
  242. {
  243.   static int count=0;
  244.   if (!(count++ & 3)) puts("\n");
  245.   put_hex((long)address_of_target(sindex));
  246.   puts(" <-- ");
  247.   put_hex(S[sindex].pagenum << 12);
  248.   puts("  ");
  249. }
  250. #endif
  251.  
  252.  
  253. static void make_free(int sindex)
  254. {
  255.   if (S[sindex].usedby == IS_MOVED) return;
  256.   if (S[sindex].usedby == recursion_start_index) {
  257.     /* we have to stop recursion and need the aux-buffer to save the page */
  258.     memcpy_page(PAGELIST->auxbuf, address_of_target(sindex));
  259.     S[S[sindex].usedby].pagenum = (unsigned long)(PAGELIST->auxbuf) >>12;
  260.   }
  261.   else {
  262.     if (S[sindex].usedby != IS_UNUSED) make_free(S[sindex].usedby); /* recursion */
  263.   }
  264.   memcpy_page(address_of_target(sindex), (void *)(S[sindex].pagenum << 12));
  265.   S[sindex].usedby = IS_MOVED;
  266. #ifdef VERBOSE
  267.   printmove(sindex);
  268. #endif
  269. }
  270.  
  271.  
  272. static void adjust(void)
  273. {
  274.   int i;
  275.   if (PAGELIST == 0) return;
  276.   build_references();
  277. #ifdef STANDALONE_DEBUG
  278.   for (i=0; i < PAGELIST->count; i++) {
  279.     printf("%3d %p source=%x usedby=%d\n",i,address_of_target(i), S[i].pagenum << 12, S[i].usedby);
  280.   }
  281. #endif
  282.   for (i=0; i < PAGELIST->count; i++) {
  283.     recursion_start_index=i;
  284.     make_free(i);
  285.     if (S[i].usedby != IS_MOVED) {
  286.       memcpy_page(address_of_target(i), (void *)(S[i].pagenum << 12));
  287.       S[i].usedby = IS_MOVED;
  288. #ifdef VERBOSE
  289.       printmove(i);
  290. #endif
  291.     }
  292.   }
  293. }
  294.  
  295.  
  296. #ifdef STANDALONE_DEBUG
  297.  
  298. static int read_pagelist(char *fname)
  299. {
  300.   FILE *f;
  301.   long v;
  302.   int i=0, bi=0, n;
  303.   
  304.   f=fopen(fname, "r");
  305.   if (!f) exit(1);
  306.   PAGELIST = malloc(0x10000);
  307.   while (fscanf(f, "%li", &v) == 1) {
  308.     if (v >= 4096) {
  309.       PAGELIST->blocks[bi].taddr=v;
  310.       PAGELIST->blocks[bi].start=i;
  311.       if (bi>0) PAGELIST->blocks[bi-1].tcount=i-PAGELIST->blocks[bi-1].start;
  312.       bi++;
  313.       PAGELIST->number_of_blocks=bi;
  314.     }
  315.     else {
  316.       S[i++].pagenum = v;
  317.     }
  318.   }
  319.   PAGELIST->count=i;
  320.   PAGELIST->blocks[bi-1].tcount=i-PAGELIST->blocks[bi-1].start;
  321.   PAGELIST->auxbuf=(void *)0x10000000;
  322. }
  323.  
  324. int main(int argc, char** argv)
  325. {
  326.   read_pagelist(argv[1]);
  327.   printf("count %d nblocks %d\n", PAGELIST->count, PAGELIST->number_of_blocks);
  328.   if (PAGELIST) adjust();
  329.   return 0;
  330. }
  331.  
  332. #else
  333.  
  334. unsigned long page_adjustment()
  335. {
  336.   int i= PAGELIST->sources[0].pagenum;
  337.   if (SCREEN_INFO.orig_video_mode == 7) {
  338.     vidmem = (char *) 0xb0000;
  339.     vidport = 0x3b4;
  340.   } else {
  341.     vidmem = (char *) 0xb8000;
  342.     vidport = 0x3d4;
  343.   }
  344.  
  345.   lines = SCREEN_INFO.orig_video_lines;
  346.   cols = SCREEN_INFO.orig_video_cols;
  347.  
  348.   if (EXT_MEM_K < (3*1024)) error("Less than 4MB of memory.\n");
  349.  
  350.   if (PAGELIST) {
  351. #ifdef VERBOSE
  352.     puts("Adjusting high loaded pages...");
  353. #endif
  354.     adjust();
  355. #ifdef VERBOSE
  356.     puts("done.\nNow starting decompressor...\n");
  357. #endif
  358.   }
  359. #ifdef VERBOSE
  360.   put_hex( REAL_STARTUP_32);
  361. #endif
  362.   return REAL_STARTUP_32;
  363. }
  364. #endif
  365.  
  366.  
  367.  
  368.  
  369.