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
Wrap
C/C++ Source or Header
|
1996-03-16
|
8KB
|
369 lines
/*
* padjust.c
*
* partially stolen from linux/arch/i386/boot/compressed/misc.c
*
*/
#ifdef STANDALONE_DEBUG
#include <stdio.h>
#include <stdlib.h>
#endif
#include <string.h>
#include <asm/segment.h>
#include <asm/io.h>
/*
* These are set up by the setup-routine at boot-time:
*/
struct screen_info {
unsigned char orig_x;
unsigned char orig_y;
unsigned char unused1[2];
unsigned short orig_video_page;
unsigned char orig_video_mode;
unsigned char orig_video_cols;
unsigned short unused2;
unsigned short orig_video_ega_bx;
unsigned short unused3;
unsigned char orig_video_lines;
unsigned char orig_video_isVGA;
};
/*
* This is set up by the setup-routine at boot-time
*/
#define EXT_MEM_K (*(unsigned short *)0x90002)
#define DRIVE_INFO (*(struct drive_info *)0x90080)
#define SCREEN_INFO (*(struct screen_info *)0x90000)
#define RAMDISK_SIZE (*(unsigned short *)0x901F8)
#define ORIG_ROOT_DEV (*(unsigned short *)0x901FC)
#define AUX_DEVICE_INFO (*(unsigned char *)0x901FF)
/* --------------------------------------------------------------------- */
/*
* This (also set up by the setup-routine) is our special extension
* Here we have all params we got from 16-bit LOADLIN
*/
struct pblock {
unsigned long taddr; /* linear address where the block of pages
must be moved to */
unsigned short start; /* index within sources of first entry */
unsigned short tcount; /* number of entries for taddr in sources */
};
struct source_entry {
unsigned long usedby:12;
unsigned long pagenum:20;
#define IS_UNUSED 0xfff
#define IS_MOVED 0xffe
};
struct pages_list {
unsigned long count; /* number of entries in 'sources' */
long number_of_blocks; /* number of valid blocks-items */
void *auxbuf; /* address of 4096 bytes auxiliary buffer */
struct pblock blocks[4];
struct source_entry sources[1]; /* list of addresses where the block of pages
currently _is_ located */
};
#ifndef STANDALONE_DEBUG
#define PAGELIST (*(struct pages_list **)0x94008)
#else
struct pages_list *PAGELIST=0;
#endif
#define S PAGELIST->sources
#define REAL_STARTUP_32 ( *((unsigned long *)0x9400C) )
/* --------------------------------------------------------------------- */
static void error(char *m);
#ifndef STANDALONE_DEBUG
static void puts(const char *);
static char *vidmem = (char *)0xb8000;
static int vidport;
static int lines, cols;
static void scroll()
{
int i;
memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 );
for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 )
vidmem[i] = ' ';
}
static void puts(const char *s)
{
int x,y,pos;
char c;
x = SCREEN_INFO.orig_x;
y = SCREEN_INFO.orig_y;
while ( ( c = *s++ ) != '\0' ) {
if ( c == '\n' ) {
x = 0;
if ( ++y >= lines ) {
scroll();
y--;
}
} else {
vidmem [ ( x + cols * y ) * 2 ] = c;
if ( ++x >= cols ) {
x = 0;
if ( ++y >= lines ) {
scroll();
y--;
}
}
}
}
SCREEN_INFO.orig_x = x;
SCREEN_INFO.orig_y = y;
pos = (x + cols * y) * 2; /* Update cursor position */
outb_p(14, vidport);
outb_p(0xff & (pos >> 9), vidport+1);
outb_p(15, vidport);
outb_p(0xff & (pos >> 1), vidport+1);
}
__ptr_t memset(__ptr_t s, int c, size_t n)
{
int i;
char *ss = (char*)s;
for (i=0;i<n;i++) ss[i] = c;
}
__ptr_t memcpy(__ptr_t __dest, __const __ptr_t __src,
size_t __n)
{
int i;
char *d = (char *)__dest, *s = (char *)__src;
for (i=0;i<__n;i++) d[i] = s[i];
}
#endif
void put_hex(unsigned long v)
{
static char table[17]="0123456789ABCDEF";
char b[9];
int i;
for (i=7; i >=0; i--) {
b[i] = table[v & 15];
v >>=4;
}
b[8]=0;
puts(b);
}
static void error(char *x)
{
puts("\n\n");
puts(x);
puts("\n\n -- System halted");
while(1); /* Halt */
}
#ifdef STANDALONE_DEBUG
static void memcpy_page(void *t,void *s)
{
printf("%p = %p\n",t,s);
}
#else
static void memcpy_page(void *t,void *s)
{
memcpy(t,s,4096);
}
#endif
static int index_within_sources(unsigned long pgnum)
{
int i;
for (i=0; i< PAGELIST->number_of_blocks; i++) {
unsigned long pstart=(PAGELIST->blocks[i].taddr >> 12);
unsigned long pstop= pstart + PAGELIST->blocks[i].tcount;
if ((pgnum >= pstart) && (pgnum < pstop)) {
return (pgnum - pstart) + PAGELIST->blocks[i].start;
}
}
return IS_UNUSED;
}
static void * address_of_target(int sindex)
{
int i, j=0;
for (i=0; i < PAGELIST->number_of_blocks; i++) {
j += PAGELIST->blocks[i].tcount;
if (sindex < j) {
return (void *)(((PAGELIST->blocks[i].taddr >> 12) + (sindex - PAGELIST->blocks[i].start)) << 12);
}
}
return 0; /* invalid */
}
static void build_references(void)
{
int i,j;
for (i=0; i < PAGELIST->count; i++) {
S[i].usedby = IS_UNUSED;
}
for (i=0; i < PAGELIST->count; i++) {
j= index_within_sources(S[i].pagenum);
if ( j != IS_UNUSED ) {
if (j == i) S[i].usedby = IS_MOVED;
else S[j].usedby = i;
}
}
}
static int recursion_start_index=0;
#ifdef VERBOSE
static printmove(int sindex)
{
static int count=0;
if (!(count++ & 3)) puts("\n");
put_hex((long)address_of_target(sindex));
puts(" <-- ");
put_hex(S[sindex].pagenum << 12);
puts(" ");
}
#endif
static void make_free(int sindex)
{
if (S[sindex].usedby == IS_MOVED) return;
if (S[sindex].usedby == recursion_start_index) {
/* we have to stop recursion and need the aux-buffer to save the page */
memcpy_page(PAGELIST->auxbuf, address_of_target(sindex));
S[S[sindex].usedby].pagenum = (unsigned long)(PAGELIST->auxbuf) >>12;
}
else {
if (S[sindex].usedby != IS_UNUSED) make_free(S[sindex].usedby); /* recursion */
}
memcpy_page(address_of_target(sindex), (void *)(S[sindex].pagenum << 12));
S[sindex].usedby = IS_MOVED;
#ifdef VERBOSE
printmove(sindex);
#endif
}
static void adjust(void)
{
int i;
if (PAGELIST == 0) return;
build_references();
#ifdef STANDALONE_DEBUG
for (i=0; i < PAGELIST->count; i++) {
printf("%3d %p source=%x usedby=%d\n",i,address_of_target(i), S[i].pagenum << 12, S[i].usedby);
}
#endif
for (i=0; i < PAGELIST->count; i++) {
recursion_start_index=i;
make_free(i);
if (S[i].usedby != IS_MOVED) {
memcpy_page(address_of_target(i), (void *)(S[i].pagenum << 12));
S[i].usedby = IS_MOVED;
#ifdef VERBOSE
printmove(i);
#endif
}
}
}
#ifdef STANDALONE_DEBUG
static int read_pagelist(char *fname)
{
FILE *f;
long v;
int i=0, bi=0, n;
f=fopen(fname, "r");
if (!f) exit(1);
PAGELIST = malloc(0x10000);
while (fscanf(f, "%li", &v) == 1) {
if (v >= 4096) {
PAGELIST->blocks[bi].taddr=v;
PAGELIST->blocks[bi].start=i;
if (bi>0) PAGELIST->blocks[bi-1].tcount=i-PAGELIST->blocks[bi-1].start;
bi++;
PAGELIST->number_of_blocks=bi;
}
else {
S[i++].pagenum = v;
}
}
PAGELIST->count=i;
PAGELIST->blocks[bi-1].tcount=i-PAGELIST->blocks[bi-1].start;
PAGELIST->auxbuf=(void *)0x10000000;
}
int main(int argc, char** argv)
{
read_pagelist(argv[1]);
printf("count %d nblocks %d\n", PAGELIST->count, PAGELIST->number_of_blocks);
if (PAGELIST) adjust();
return 0;
}
#else
unsigned long page_adjustment()
{
int i= PAGELIST->sources[0].pagenum;
if (SCREEN_INFO.orig_video_mode == 7) {
vidmem = (char *) 0xb0000;
vidport = 0x3b4;
} else {
vidmem = (char *) 0xb8000;
vidport = 0x3d4;
}
lines = SCREEN_INFO.orig_video_lines;
cols = SCREEN_INFO.orig_video_cols;
if (EXT_MEM_K < (3*1024)) error("Less than 4MB of memory.\n");
if (PAGELIST) {
#ifdef VERBOSE
puts("Adjusting high loaded pages...");
#endif
adjust();
#ifdef VERBOSE
puts("done.\nNow starting decompressor...\n");
#endif
}
#ifdef VERBOSE
put_hex( REAL_STARTUP_32);
#endif
return REAL_STARTUP_32;
}
#endif