static int set_bios_mode(u8 mode)
{
	struct biosregs ireg, oreg;
	u8 new_mode;

	initregs(&ireg);
	ireg.al = mode;		/* AH=0x00 Set Video Mode */
	intcall(0x10, &ireg, NULL);

	ireg.ah = 0x0f;		/* Get Current Video Mode */
	intcall(0x10, &ireg, &oreg);

	do_restore = 1;		/* Assume video contents were lost */

	/* Not all BIOSes are clean with the top bit */
	new_mode = oreg.al & 0x7f;

	if (new_mode == mode)
		return 0;	/* Mode change OK */

#ifndef _WAKEUP
	if (new_mode != boot_params.screen_info.orig_video_mode) {
		/* Mode setting failed, but we didn't end up where we
		   started.  That's bad.  Try to revert to the original
		   video mode. */
		ireg.ax = boot_params.screen_info.orig_video_mode;
		intcall(0x10, &ireg, NULL);
	}
#endif
	return -1;
}
Example #2
0
static int detect_memory_e801(void)
{
	struct biosregs ireg, oreg;

	initregs(&ireg);
	ireg.ax = 0xe801;
	intcall(0x15, &ireg, &oreg);

	if (oreg.eflags & X86_EFLAGS_CF)
		return -1;

	/*                               */
	if (oreg.cx || oreg.dx) {
		oreg.ax = oreg.cx;
		oreg.bx = oreg.dx;
	}

	if (oreg.ax > 15*1024) {
		return -1;	/*        */
	} else if (oreg.ax == 15*1024) {
		boot_params.alt_mem_k = (oreg.bx << 6) + oreg.ax;
	} else {
		/*
                                                       
                                                     
                                                  
                                                     
         
   */
		boot_params.alt_mem_k = oreg.ax;
	}

	return 0;
}
Example #3
0
void cleanscreen(void) {
  struct biosregs ireg;
  initregs(&ireg);
  ireg.bh = 0x0f;
  ireg.cx = 0x0;
  ireg.dh = 24;
  ireg.dl = 79;
  ireg.ax = 0x0600;
  intcall(0x10, &ireg, NULL);

  initregs(&ireg);
  ireg.ah = 0x2;
  ireg.bx = 0;
  ireg.dx = 0;
  intcall(0x10, &ireg, NULL);
}
Example #4
0
static int detect_memory_e801(void)
{
	struct biosregs ireg, oreg;

	initregs(&ireg);
	ireg.ax = 0xe801;
	intcall(0x15, &ireg, &oreg);

	if (oreg.eflags & X86_EFLAGS_CF)
		return -1;

	/* Do we really need to do this? */
	if (oreg.cx || oreg.dx) {
		oreg.ax = oreg.cx;
		oreg.bx = oreg.dx;
	}

	if (oreg.ax > 15*1024) {
		return -1;	/* Bogus! */
	} else if (oreg.ax == 15*1024) {
		boot_params.alt_mem_k = (oreg.bx << 6) + oreg.ax;
	} else {
		/*
		 * This ignores memory above 16MB if we have a memory
		 * hole there.  If someone actually finds a machine
		 * with a memory hole at 16MB and no support for
		 * 0E820h they should probably generate a fake e820
		 * map.
		 */
		boot_params.alt_mem_k = oreg.ax;
	}

	return 0;
}
Example #5
0
static void __bootcode enable_a20_bios(void)
{
	struct biosregs ireg;

	initregs(&ireg);
	ireg.ax = 0x2401;
	intcall(0x15, &ireg, NULL);
}
Example #6
0
static int kbd_pending(void)
{
    struct biosregs ireg, oreg;

    initregs(&ireg);
    ireg.ah = 0x01;
    intcall(0x16, &ireg, &oreg);

    return !(oreg.eflags & X86_EFLAGS_ZF);
}
Example #7
0
/*
 * Read from the keyboard
 */
int getchar(void)
{
    struct biosregs ireg, oreg;

    initregs(&ireg);
    /* ireg.ah = 0x00; */
    intcall(0x16, &ireg, &oreg);

    return oreg.al;
}
Example #8
0
static u8 gettime(void)
{
    struct biosregs ireg, oreg;

    initregs(&ireg);
    ireg.ah = 0x02;
    intcall(0x1a, &ireg, &oreg);

    return oreg.dh;
}
Example #9
0
int query_apm_bios(void)
{
	struct biosregs ireg, oreg;

	/* APM BIOS installation check */
	initregs(&ireg);
	ireg.ah = 0x53;
	intcall(0x15, &ireg, &oreg);

	if (oreg.flags & X86_EFLAGS_CF)
		return -1;		/* No APM BIOS */

	if (oreg.bx != 0x504d)		/* "PM" signature */
		return -1;

	if (!(oreg.cx & 0x02))		/* 32 bits supported? */
		return -1;

	/* Disconnect first, just in case */
	ireg.al = 0x04;
	intcall(0x15, &ireg, NULL);

	/* 32-bit connect */
	ireg.al = 0x03;
	intcall(0x15, &ireg, &oreg);

	boot_params.apm_bios_info.cseg        = oreg.ax;
	boot_params.apm_bios_info.offset      = oreg.ebx;
	boot_params.apm_bios_info.cseg_16     = oreg.cx;
	boot_params.apm_bios_info.dseg        = oreg.dx;
	boot_params.apm_bios_info.cseg_len    = oreg.si;
	boot_params.apm_bios_info.cseg_16_len = oreg.hsi;
	boot_params.apm_bios_info.dseg_len    = oreg.di;

	if (oreg.flags & X86_EFLAGS_CF)
		return -1;

	/* Redo the installation check as the 32-bit connect;
	   some BIOSes return different flags this way... */

	ireg.al = 0x00;
	intcall(0x15, &ireg, &oreg);

	if ((oreg.eflags & X86_EFLAGS_CF) || oreg.bx != 0x504d) {
		/* Failure with 32-bit connect, try to disconect and ignore */
		ireg.al = 0x04;
		intcall(0x15, &ireg, NULL);
		return -1;
	}

	boot_params.apm_bios_info.version = oreg.ax;
	boot_params.apm_bios_info.flags   = oreg.cx;
	return 0;
}
Example #10
0
static void __attribute__((section(".inittext"))) bios_putchar(int ch)
{
    struct biosregs ireg;

    initregs(&ireg);
    ireg.bx = 0x0007;
    ireg.cx = 0x0001;
    ireg.ah = 0x0e;
    ireg.al = ch;
    intcall(0x10, &ireg, NULL);
}
Example #11
0
static int detect_memory_e820(void)
{
	int count = 0;
	struct biosregs ireg, oreg;
	struct e820entry *desc = boot_params.e820_map;
	static struct e820entry buf; /*                        */

	initregs(&ireg);
	ireg.ax  = 0xe820;
	ireg.cx  = sizeof buf;
	ireg.edx = SMAP;
	ireg.di  = (size_t)&buf;

	/*
                                                           
                                                         
                                                                    
                                                                  
   
                                                         
                                                           
                                                               
                                                          
                                                              
                                                              
  */

	do {
		intcall(0x15, &ireg, &oreg);
		ireg.ebx = oreg.ebx; /*                       */

		/*                                                        
                                                          
                                */
		if (oreg.eflags & X86_EFLAGS_CF)
			break;

		/*                                                 
                                                         
                                                      
                                                       
                          */
		if (oreg.eax != SMAP) {
			count = 0;
			break;
		}

		*desc++ = buf;
		count++;
	} while (ireg.ebx && count < ARRAY_SIZE(boot_params.e820_map));

	return boot_params.e820_entries = count;
}
static int detect_memory_e820(void)
{
	int count = 0;
	struct biosregs ireg, oreg;
	struct e820entry *desc = boot_params.e820_map;
	static struct e820entry buf; /* static so it is zeroed */

	initregs(&ireg);
	ireg.ax  = 0xe820;
	ireg.cx  = sizeof buf;
	ireg.edx = SMAP;
	ireg.di  = (size_t)&buf;

	/*
	 * Note: at least one BIOS is known which assumes that the
	 * buffer pointed to by one e820 call is the same one as
	 * the previous call, and only changes modified fields.  Therefore,
	 * we use a temporary buffer and copy the results entry by entry.
	 *
	 * This routine deliberately does not try to account for
	 * ACPI 3+ extended attributes.  This is because there are
	 * BIOSes in the field which report zero for the valid bit for
	 * all ranges, and we don't currently make any use of the
	 * other attribute bits.  Revisit this if we see the extended
	 * attribute bits deployed in a meaningful way in the future.
	 */

	do {
		intcall(0x15, &ireg, &oreg);
		ireg.ebx = oreg.ebx; /* for next iteration... */

		/* BIOSes which terminate the chain with CF = 1 as opposed
		   to %ebx = 0 don't always report the SMAP signature on
		   the final, failing, probe. */
		if (oreg.eflags & X86_EFLAGS_CF)
			break;

		/* Some BIOSes stop returning SMAP in the middle of
		   the search loop.  We don't know exactly how the BIOS
		   screwed up the map at that point, we might have a
		   partial map, the full map, or complete garbage, so
		   just return failure. */
		if (oreg.eax != SMAP) {
			count = 0;
			break;
		}

		*desc++ = buf;
		count++;
	} while (ireg.ebx && count < ARRAY_SIZE(boot_params.e820_map));

	return boot_params.e820_entries = count;
}
Example #13
0
/**
 @brief	0x88 Interrupt 명령으로 메모리\n
	 1Kbyte 단위의 메모리 크기를 확인한다.\n
	 확인 가능한 최대 메모리 크기는 64M + 1M 이다.\n
	 확인된 결과값은 boot_params.screen_info.ext_mem_k 에 저장된다.
 @return	성공시:0, 실패시:-1
 */
static int detect_memory_88(void)
{
	struct biosregs ireg, oreg;

	initregs(&ireg);
	ireg.ah = 0x88;
	intcall(0x15, &ireg, &oreg);

	boot_params.screen_info.ext_mem_k = oreg.ax;

	return -(oreg.eflags & X86_EFLAGS_CF); /* 0 or -1 */
}
Example #14
0
static int vesa_probe(void)
{
	struct biosregs ireg, oreg;
	u16 mode;
	addr_t mode_ptr;
	struct mode_info *mi;
	int nmodes = 0;

	video_vesa.modes = GET_HEAP(struct mode_info, 0);

	initregs(&ireg);
	ireg.ax = 0x4f00;
	ireg.di = (size_t)&vginfo;
	intcall(0x10, &ireg, &oreg);

	if (oreg.ax != 0x004f ||
	    vginfo.signature != VESA_MAGIC ||
	    vginfo.version < 0x0102)
		return 0;	/* Not present */

	set_fs(vginfo.video_mode_ptr.seg);
	mode_ptr = vginfo.video_mode_ptr.off;

	while ((mode = rdfs16(mode_ptr)) != 0xffff) {
		mode_ptr += 2;

		if (!heap_free(sizeof(struct mode_info)))
			break;	/* Heap full, can't save mode info */

		if (mode & ~0x1ff)
			continue;

		memset(&vminfo, 0, sizeof vminfo); /* Just in case... */

		ireg.ax = 0x4f01;
		ireg.cx = mode;
		ireg.di = (size_t)&vminfo;
		intcall(0x10, &ireg, &oreg);

		if (oreg.ax != 0x004f)
			continue;

		if ((vminfo.mode_attr & 0x15) == 0x05) {
			/* Text Mode, TTY BIOS supported,
			   supported by hardware */
			mi = GET_HEAP(struct mode_info, 1);
			mi->mode  = mode + VIDEO_FIRST_VESA;
			mi->depth = 0; /* text */
			mi->x     = vminfo.h_res;
			mi->y     = vminfo.v_res;
			nmodes++;
		} else if ((vminfo.mode_attr & 0x99) == 0x99 &&
Example #15
0
void putchar(int ch) {
  struct biosregs ireg;

  if (ch == '\n')
    putchar('\r');  /* \n -> \r\n */

  initregs(&ireg);
  ireg.bx = 0x0007;
  ireg.cx = 0x0001;
  ireg.ah = 0x0e;
  ireg.al = ch;
  intcall(0x10, &ireg, NULL);
}
Example #16
0
static int read_mbr(u8 devno, void *buf)
{
	struct biosregs ireg, oreg;

	initregs(&ireg);
	ireg.ax = 0x0201;		
	ireg.cx = 0x0001;		
	ireg.dl = devno;
	ireg.bx = (size_t)buf;

	intcall(0x13, &ireg, &oreg);

	return -(oreg.eflags & X86_EFLAGS_CF); 
}
Example #17
0
void __attribute__((section(".inittext"))) putchar(int ch)
{
	struct biosregs ireg;

	if (ch == '\n')
		putchar('\r');	/* \n -> \r\n */

	initregs(&ireg);
	ireg.bx = 0x0007;
	ireg.cx = 0x0001;
	ireg.ah = 0x0e;
	ireg.al = ch;
	intcall(0x10, &ireg, NULL);
}
Example #18
0
static int get_edd_info(u8 devno, struct edd_info *ei)
{
	struct biosregs ireg, oreg;

	memset(ei, 0, sizeof *ei);

	

	initregs(&ireg);
	ireg.ah = 0x41;
	ireg.bx = EDDMAGIC1;
	ireg.dl = devno;
	intcall(0x13, &ireg, &oreg);

	if (oreg.eflags & X86_EFLAGS_CF)
		return -1;	

	if (oreg.bx != EDDMAGIC2)
		return -1;

	ei->device  = devno;
	ei->version = oreg.ah;		 
	ei->interface_support = oreg.cx; 

	

	ei->params.length = sizeof(ei->params);
	ireg.ah = 0x48;
	ireg.si = (size_t)&ei->params;
	intcall(0x13, &ireg, &oreg);

	

	
	ireg.ah = 0x08;
	ireg.es = 0;
	intcall(0x13, &ireg, &oreg);

	if (!(oreg.eflags & X86_EFLAGS_CF)) {
		ei->legacy_max_cylinder = oreg.ch + ((oreg.cl & 0xc0) << 2);
		ei->legacy_max_head = oreg.dh;
		ei->legacy_sectors_per_track = oreg.cl & 0x3f;
	}

	return 0;
}
Example #19
0
File: mca.c Project: 03199618/linux
int query_mca(void)
{
	struct biosregs ireg, oreg;
	u16 len;

	initregs(&ireg);
	ireg.ah = 0xc0;
	intcall(0x15, &ireg, &oreg);

	if (oreg.eflags & X86_EFLAGS_CF)
		return -1;	/* No MCA present */

	set_fs(oreg.es);
	len = rdfs16(oreg.bx);

	if (len > sizeof(boot_params.sys_desc_table))
		len = sizeof(boot_params.sys_desc_table);

	copy_from_fs(&boot_params.sys_desc_table, oreg.bx, len);
	return 0;
}
Example #20
0
/**
 @brief	0xe801 Interrupt 명령을 통한 Memory map을 확인한다.\n
	 확인된 Memory map 정보는 boot_params 에 저장된다.\n
	 확인하는 사항은 전체 메모리 맵 구성의 크기이다.\n
	 확인 가능한 최대 메모리 크기는 4G + 16M 이다.\n
	 최대 확인 가능한 메모리 크기까지만 표현한다.\n
	 결과값은 boot_params.alt_mem_k 에 저장된다.
 @return	성공시:0, 실패시:-1
 */
static int detect_memory_e801(void)
{
	struct biosregs ireg, oreg;

	initregs(&ireg);
	ireg.ax = 0xe801;
	// 0xe801 : 0xe820(2002), 0xe801(1994) 2002 년 이전의 CPU는 e801
	// 명령으로만 Memory map 을 확인할 수 있으므로...
	intcall(0x15, &ireg, &oreg);
	// 연산 결과
	// ax : Kbyte 단위의 1 ~ 15 * 1024 사이의 크기 값.(표현가능한 크기: 1Kbyte ~ 15 Mbyte)
	// bx : 64KByte 단위의 크기값. (최대 4GB)

	if (oreg.eflags & X86_EFLAGS_CF)
		return -1;

	/* Do we really need to do this? */
	if (oreg.cx || oreg.dx) {
		oreg.ax = oreg.cx;
		oreg.bx = oreg.dx;
	}

	if (oreg.ax > 15*1024) {
		return -1;	/* Bogus! */
	} else if (oreg.ax == 15*1024) {
		boot_params.alt_mem_k = (oreg.bx << 6) + oreg.ax;
	} else {
		/*
		 * This ignores memory above 16MB if we have a memory
		 * hole there.  If someone actually finds a machine
		 * with a memory hole at 16MB and no support for
		 * 0E820h they should probably generate a fake e820
		 * map.
		 */
		boot_params.alt_mem_k = oreg.ax;
	}

	return 0;
}
static int detect_memory_e801(void)
{
	struct biosregs ireg, oreg;

	initregs(&ireg);
	ireg.ax = 0xe801;
	intcall(0x15, &ireg, &oreg);

	if (oreg.eflags & X86_EFLAGS_CF)
		return -1;

	/* Do we really need to do this? */
	if (oreg.cx || oreg.dx) {
		oreg.ax = oreg.cx;
		oreg.bx = oreg.dx;
	}

	if (oreg.ax > 15*1024) {
		return -1;	/* Bogus! */
	} else if (oreg.ax == 15*1024) {
<<<<<<< HEAD
		boot_params.alt_mem_k = (oreg.bx << 6) + oreg.ax;
=======
Example #22
0
/**
 @brief	e820 Interrupt 를 통한 현재 Memory map 구성을 확인하고 e820 정보를 e820_map에 입력한다.
 @return	성공시: 확인된 memory map 구성 갯수, 실패시:0
 */
static int detect_memory_e820(void)
{
	int count = 0;
	struct biosregs ireg, oreg;
	struct e820entry *desc = boot_params.e820_map;
	static struct e820entry buf; /* static so it is zeroed */

	initregs(&ireg);
	ireg.ax  = 0xe820;		// 0xE820
	// 0xE820 : returns a memory map of all the installed RAM,
	// and of physical memory ranges reserved by the BIOS.
	// http://www.uruk.org/orig-grub/mem64mb.html
	ireg.cx  = sizeof buf;
	ireg.edx = SMAP;	/* 필요한 signature */
	ireg.di  = (size_t)&buf;

	/*
	 * Note: at least one BIOS is known which assumes that the
	 * buffer pointed to by one e820 call is the same one as
	 * the previous call, and only changes modified fields.  Therefore,
	 * we use a temporary buffer and copy the results entry by entry.
	 *
	 * This routine deliberately does not try to account for
	 * ACPI 3+ extended attributes.  This is because there are
	 * BIOSes in the field which report zero for the valid bit for
	 * all ranges, and we don't currently make any use of the
	 * other attribute bits.  Revisit this if we see the extended
	 * attribute bits deployed in a meaningful way in the future.
	 */

	do {
		intcall(0x15, &ireg, &oreg);
		// 0x15: ax(e820)
		// &ireg : Input Register
		// &oreg : Ouput Register
		ireg.ebx = oreg.ebx; /* for next iteration... */
		// ebx : Offset 주소.
		// Input 의 경우 시작 Offset, Output의 경우 다음 Offset.
		// 만약 Offset이 0 이면 끝을 의미한다.

		/* BIOSes which terminate the chain with CF = 1 as opposed
		   to %ebx = 0 don't always report the SMAP signature on
		   the final, failing, probe. */
		if (oreg.eflags & X86_EFLAGS_CF)	// Error 발생시, CF Flag가 Set이 된다.
			break;

		/* Some BIOSes stop returning SMAP in the middle of
		   the search loop.  We don't know exactly how the BIOS
		   screwed up the map at that point, we might have a
		   partial map, the full map, or complete garbage, so
		   just return failure. */
		// 정상적인 검색 루프에서는 Return 값으로 oreg.eax 에 SMAP 값이 입력되어야 한다.
		// 일부 BIOS 에서는 다른 값들이 올 수도 있지만 SMAP 이 아닌 경우,
		// 모두 Error 로 간주한다.
		if (oreg.eax != SMAP) {
			count = 0;
			break;
		}

		*desc++ = buf; 	/* e820 엔트리를 e820_map에 입력 */
		count++;
		// ireg.ebx = Next Search Memory Offset
	} while (ireg.ebx && count < ARRAY_SIZE(boot_params.e820_map));

	return boot_params.e820_entries = count; /* 총 갯수 */
}