⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 probe.c

📁 linux 的引导程序源码The Microsoft&reg Windows&reg Software Development Kit (SDK) provides the documentation
💻 C
📖 第 1 页 / 共 2 页
字号:
/* probe.c -- BIOS probes *//*Copyright 1999-2002 John Coffman.All rights reserved.Licensed under the terms contained in the file 'COPYING' in the source directory.*//*#define DEBUG*/#define VIDEO 1#include <stdlib.h>#include <unistd.h>#include <stdio.h>#include <string.h>#include <ctype.h>#include <fcntl.h>#include <errno.h>#include <sys/stat.h>#include <sys/types.h>#include <linux/unistd.h>#include "common.h"#include "device.h"#include "geometry.h"#include "partition.h"#include "bsect.h"#include "bdata.h"#include "probe.h"/*#include "lrmi.h"*/#ifdef LCF_BDATA#if BD_MAX_FLOPPY > 4#error "too many floppies in  bdata.h"#endif#if BD_MAX_HARD > 16#error "too many hard disks in  bdata.h"#endif#if BD_GET_VIDEO > 3#error "video get level set too high in  bdata.h"#endif#endifstatic union Buf {   unsigned char b[4*SECTOR_SIZE];   struct {      short checksum[2];	/* prevent alignment on *4 boundary */      char signature[4];      short version;      short length;      unsigned char disk;	/* device code of last good disk */      unsigned char vid, mflp, mhrd;      short floppy;		/* byte offset to floppy data    */      short hard;		/* byte offset to hard disk data */      short partitions;		/* byte offset to partition info */      video_t v;      floppy_t f[4];      hard_t d;/*      edd_t edd; */   } s;} buf;static int buf_valid = 0;static hard_t *hdp[16+1] =		/* pointers to all the hard disks */	{	NULL, NULL, NULL, NULL, 		NULL, NULL, NULL, NULL, 		NULL, NULL, NULL, NULL, 		NULL, NULL, NULL, NULL,  NULL	};static char warned[16];static void do_ebda(void);static void do_cr_pr(void);static void do_help(void);static void do_geom(char *bios);static void do_bitmap(char *file);static void do_geom_all(void);static void do_table(char *part);#if VIDEOstatic void do_video(void);#endifstatic char dev[] = "<device>";extern CHANGE_RULE *change_rules;	/* defined in partition.c */#if 0   /* def LCF_ALL_PARTITIONS */#define LLSECTORSIZE ((long long)SECTOR_SIZE)       _syscall5(int,  _llseek,  uint,  fd, ulong, hi, ulong, lo,       loff_t *, res, uint, wh);       int _llseek(unsigned int fd,  unsigned  long  offset_high,       unsigned  long  offset_low,  loff_t * result, unsigned int       whence);              loff_t llseek(unsigned int fd, loff_t offs, unsigned int whence)       { loff_t res;       	return _llseek(fd, offs>>32, offs, &res, whence) < 0  ?       			 (loff_t)(-1) : res;       }#endifstaticstruct Probes {	char *cmd;	void (*prc)();	char *str;	char *help;	}	list[] = {{ "help",  do_help,  NULL,  "Print list of -T(ell) options"	},{ "bitmap=",do_bitmap,"<file>", "Display .bmp file X,Y/color/timer information"},{ "ChRul", do_cr_pr, NULL,  "List partition change-rules"  },{ "EBDA",  do_ebda,  NULL,  "Extended BIOS Data Area information" },{ "geom=", do_geom,  "<bios>", "Geometry CHS data for BIOS code 0x80, etc." },{ "geom" , do_geom_all, NULL, "Geometry for all BIOS drives" },{ "table=", do_table, dev, "Partition table information for /dev/hda, etc."},#if VIDEO{ "video", do_video, NULL,  "Graphic mode information" },#endif{ NULL,    NULL,     NULL,   NULL}	};static struct partitions {	char *name;	unsigned char type;	unsigned char hide;	} ptab [] = {		/* Not complete, by any means */    { "DOS12", PART_DOS12, HIDDEN_OFF },    { "DOS16_small", PART_DOS16_SMALL, HIDDEN_OFF },    { "DOS16_big", PART_DOS16_BIG, HIDDEN_OFF },    { "NTFS or OS2_HPFS", PART_NTFS, HIDDEN_OFF },	/* same as HPFS; keep these two together *//*  { "HPFS", PART_HPFS, HIDDEN_OFF },	*/	/* same as NTFS */    { "FAT32", PART_FAT32, HIDDEN_OFF },    { "FAT32_lba", PART_FAT32_LBA, HIDDEN_OFF },    { "FAT16_lba", PART_FAT16_LBA, HIDDEN_OFF },    { "OS/2 BootMgr", PART_OS2_BOOTMGR, 0 },    { "DOS extended", PART_DOS_EXTD, 0 },    { "WIN extended", PART_WIN_EXTD_LBA, 0 },    { "Linux ext'd", PART_LINUX_EXTD, 0 },    { "Linux Swap", PART_LINUX_SWAP, 0 },    { "Linux Native", PART_LINUX_NATIVE, 0 },    { "Minix", PART_LINUX_MINIX, 0 },    { "Linux RAID", 0xfd, 0 },    { NULL, 0, 0 }   };static char phead[] = "\t\t Type  Boot      Start           End      Sector    #sectors";/* load the low memory bios data area *//*  0 = no error, !0 = error on get */static int fetch(void){    int fd;    int got, get;    int at = 0, seek = PROBESEG*16;        if (buf_valid) return 0;        if ((fd=open("/dev/mem", O_RDONLY)) < 0) return 1;#if 0    while (at<seek) {	get = seek - at > sizeof(buf.b) ? sizeof(buf.b) : seek - at;	got = read(fd, &buf.b, get);	if (got != get) return 1;	at += got;    }#else    at = lseek(fd, seek, SEEK_SET);    if (at != seek) return 1;#endif    get = sizeof(buf.b);    if (read(fd, &buf.b, get) != get) return 1;    close(fd);        if (strncmp(buf.s.signature, PROBE_SIGNATURE,4)) return 2;/*    got = buf.s.version; */	/* quiet GCC */    if (buf.s.version < 3 ||        buf.s.version > (short)(PROBE_VERSION)) return 3;    got = buf.s.length;    if (got > sizeof(buf.b) || got < sizeof(buf.s)) return 4;    if (*(long*)buf.s.checksum != crc32((char*)&buf.s + 4, got-4, CRC_POLY1))    	return 5;    buf_valid = 1;        return 0;}/* print out the help page for -T flag */static void do_help(void){    struct Probes *pr;        printf("usage:");    for (pr=list; pr->cmd; pr++) {    	printf("\tlilo -T %s%s\t%s\n",     			pr->cmd,     			pr->str ? pr->str : "        ",    			pr->help);    }#ifdef DEBUG    printf("    In some cases, the '-v' flag will produce more output.\n");    printf("sizeof(video_t) = %d  sizeof(floppy_t) = %d  sizeof(hard_t) = %d\n"           "sizeof(edd_t) = %d  sizeof(buf.s) = %d\n",            sizeof(video_t),  sizeof(floppy_t), sizeof(hard_t), sizeof(edd_t),            sizeof(buf.s) );	    printf("fetch returns %d\n", fetch());            #endif}/* diagnostic output */static void show_geom(char *who, int cyl, int head, int sect){   fprintf(errstd, "    %s: %d cylinders, %d heads, %d sectors\n", who, cyl, head, sect);}/* get the old BIOS disk geometry */static int get_geom(unsigned int drive, struct disk_geom *geom){    hard_t *hd;    floppy_t *fd;    int i;    struct partition *pt_base;    if((i=fetch())) {        printf("No drive geometry information is available.\n\n");        exit(0);    }#ifdef DEBUG	printf("get_geom: drive = 0x%02X\n", drive);	fflush(stdout);#endif    if (drive >= 0 && drive < buf.s.mflp) {	fd = (floppy_t*)&buf.b[buf.s.floppy] + drive;	hd = (hard_t*)fd;    }    else if (drive == 0x80) {	hdp[drive-0x80] = hd = (hard_t*)&buf.b[buf.s.hard];    }        else if (drive >= 0x81 && drive < 0x80+buf.s.mhrd) {	if (drive > buf.s.disk) return 1;	if (!hdp[drive-0x80]) {	    i = get_geom(drive-1, geom);#ifdef DEBUG		printf("get_geom recursive return = %d  AH=0x%02X\n", i, i-1);		fflush(stdout);#endif	    if (i) return i;	}	hd = hdp[drive-0x80];    } else return 1;#ifdef DEBUG	printf("get_geom:  hd = %08X\n", (int)hd);	fflush(stdout);#endif        memset(geom, 0, sizeof(*geom));    if (drive >= 0x80)        hdp[drive-0x80 + 1] = (void*)hd + sizeof(hard_t);		/* simplest increment, but may be wrong */        /* regs.eax = 0x1500;           check drive type */    /* regs.edx = drive;			*/#ifdef DEBUG	printf("get_geom: int13, fn=15\n");	fflush(stdout);#endif      if (hd->fn15.flags & 1)   return 1;	/* carry was set */   geom->type = hd->fn15.ah;   if (geom->type == 0) return 1;   if (geom->type == 3)     geom->n_total_blocks = ((int)hd->fn15.cx << 16) + hd->fn15.dx;      /* regs.eax = 0x0800;		*/   /* regs.edx = drive;			*/   #ifdef DEBUG	printf("get_geom: int13, fn=08\n");	fflush(stdout);#endif      if (hd->fn08.flags&1 || hd->fn08.ah || hd->fn08.cx==0)     return 1 + hd->fn08.ah;      geom->n_sect = hd->fn08.cx & 0x3F;   geom->n_head = ((hd->fn08.dx>>8)&0xFF)+1;   geom->n_cyl  = (((hd->fn08.cx>>8)&0xFF)|((hd->fn08.cx&0xC0)<<2))+1;   geom->n_disks = hd->fn08.dx & 0xFF;   geom->pt = NULL;   if (drive < 4)  return 0;      pt_base = NULL;   if (buf.s.disk) {	pt_base = (struct partition *)&buf.b[buf.s.partitions];   }   if (pt_base && drive <= (int)buf.s.disk) {#if 0   				geom->pt = &pt_base[(drive&15)*4];#else	void *p = (void*)pt_base;	int i = buf.s.version >= 4 ? 8 : 0;		p += (drive & 15) * (PART_TABLE_SIZE + i) + i;	geom->pt = (struct partition *)p;	if (i) geom->serial_no = *(int*)(p-6);#endif   }#ifdef DEBUG   printf("get_geom:  PT->%08X  S/N=%08X\n", (int)geom->pt, geom->serial_no);#endif         /* regs.eax = 0x4100;      check EDD extensions present */   /* regs.edx = drive;				*/   /* regs.ebx = 0x55AA;			*/#ifdef DEBUG	printf("get_geom: int13, fn=41\n");	fflush(stdout);#endif   if ((hd->fn41.flags&1)==0 && (hd->fn41.bx)==(unsigned short)0xAA55) {      geom->EDD_flags = hd->fn41.cx;      geom->EDD_rev = hd->fn41.ah;   }      if ((geom->EDD_flags) & EDD_SUBSET) {      edd_t *dp;      dp = (edd_t*)hdp[drive-0x80 + 1];#ifdef DEBUG	printf("get_geom:  EDD  dp = %08X\n", (int)dp);	fflush(stdout);#endif    /* update the pointer to the next drive */      hdp[drive-0x80 + 1] = (void*)dp + sizeof(edd_t);      /* regs.eax = 0x4800;		*/      /* regs.edx = drive;		*/      #ifdef DEBUG	printf("get_geom: int13, fn=48\n");	fflush(stdout);#endif            if ((dp->info) & EDD_PARAM_GEOM_VALID) {         if ((geom->n_sect != dp->sectors ||             geom->n_head != dp->heads) && !nowarn && !(warned[drive-0x80]&1) ) {                fprintf(errstd,"Warning: Int 0x13 function 8 and function 0x48 return different\n"                               "head/sector geometries for BIOS drive 0x%02X\n", drive);                show_geom("fn 08", geom->n_cyl, geom->n_head, geom->n_sect);                show_geom("fn 48", dp->cylinders, dp->heads, dp->sectors);		warned[drive-0x80] |= 1;	    }/* prefer to return the fn 8 geometry */#if 0         geom->n_cyl  = dp->cylinders;         geom->n_head = dp->heads;         geom->n_sect = dp->sectors;#endif	 if (dp->total_sectors > geom->n_total_blocks)		geom->n_total_blocks = dp->total_sectors;      }   }      return 0;}/* get the conventional memory size in Kb */static int get_conv_mem(void){    if(fetch()) {        printf("No memory information is available.\n\n");        exit(0);    }    return (int)buf.s.v.mem;}/* print the conventional memory size */static void do_ebda(void){    int m, n, init;    static char EBDA[]="Extended BIOS Data Area (EBDA)";        m = get_conv_mem();    if (m==640) printf("    no %s\n", EBDA);    else printf("    %s = %dK\n", EBDA, 640-m);    printf("    Conventional Memory = %dK    0x%06X\n", m, m<<10);    m <<= 10;    m -= 0x200;#ifndef LCF_BUILTIN    n = m - (MAX_SECONDARY+4+MAX_DESCR_SECS)*SECTOR_SIZE;#else    n = (select_loader()->size + SECTOR_SIZE - 1) / SECTOR_SIZE;    n = m - (n+4+MAX_DESCR_SECS)*SECTOR_SIZE;#endif    init = (n - (MAX_SETUPSECS+1)*SECTOR_SIZE)>>4;    if (init > DEF_INITSEG) init = DEF_INITSEG;#if 0    if (!(verbose>0)) return;#else    printf("\n");#endif    printf("    The First stage loader boots at:  0x%08X  (0000:%04X)\n",    			FIRSTSEG<<4, FIRSTSEG<<4);    printf("    The Second stage loader runs at:  0x%08X  (%04X:%04X)\n",    			n, n>>4, n&15);    printf("    The kernel cmdline is passed at:  0x%08X  (%04X:%04X)\n",    			m, init, m-(init<<4));}/* print the CHS geometry information for the specified disk */static void print_geom(int dr, struct disk_geom geom){    char ch_ser[12] = { 0 };    if (geom.serial_no) sprintf(ch_ser, "%08X", geom.serial_no);    printf("    bios=0x%02x, cylinders=%d, heads=%d, sectors=%d\t%s\n", 	dr, geom.n_cyl, geom.n_head, geom.n_sect, ch_ser);    if (geom.EDD_flags & EDD_PACKET)    printf("\tEDD packet calls allowed\n");}/* print disk drive geometry for all drives */static void do_geom_all(void){   int d, hd, dr;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -