Int 15/AX=E820h ,Int 15/AX=E801h

来源:互联网 发布:天猫等级和淘宝等级 编辑:程序博客网 时间:2024/06/01 10:20

Int 15/AX=E820h 是用来获取系统中的内存映地址描述符的,操作系统常用来获取内存大小.

PS:内存(Memory)可以是我们平时所说的在主板上的内存条,我们称作Base Memory,也可以是毗边
Base Memory 的并作为普通内存扩展的内存.

 

首先来了解一下相关的数据结构:

Format of Phoenix BIOS system memory map address range descriptor
(BIOS系统内存映射地址描述符格式,通常在英文中被称作Entry,一个Entry描述一种系统内存信息):

Offset  Size    Description    
00h    QWORD   base address    #系统内存块基地址
08h    QWORD   length in bytes #系统内存大小
10h    DWORD   type of address range #内存类型,看下面的(Values for System Memory Map address type)

这个结构块的大小为20

格式:

AX = E820hEAX = 0000E820hEDX = 534D4150h ('SMAP')EBX = continuation value or 00000000h to start at beginning of map
持续值 或者 等于00000000h,以便重map的开头开始scanECX = size of buffer for result, in bytes (should be >= 20 bytes)ES:DI -> buffer for result

Return:
CF clear if successful

EAX = 534D4150h ('SMAP')ES:DI buffer filledEBX = next offset from which to copy or 00000000h if all doneECX = 传送到缓冲区buf的Entry的大小,一般为20个字节,ECX=20CF set on errorAH = error code (86h)
Reference:http://www.ctyme.com/intr/rb-1741.htm
除了Base Memory外,他还返回芯片集定义的系统内存地址空洞,而这些空洞是没有被使用的,是
主板内存映射设备和BIOS所保留的.
Values for System Memory Map address type:01h    memory, available to OS02h    reserved, not available (e.g. system ROM, memory-mapped device)03h    ACPI Reclaim Memory (usable by OS after reading ACPI tables)04h    ACPI NVS Memory (OS is required to save this memory between NVSsessions)other  not defined yet -- treat as Reserved
原理描述:
调用此功能可以从系统某一个地方(这里存放有一个List(列表),这个列表里存放的都是一个个的
Entry)通过设置EBX(20的倍数)的值,然后调用int 0x15就可以讲EBX所指向的Entry拷贝
到ES:DI所指向的内存区)
 

Linux2.4.10-setup.S中关于内存检测(E820h)注释及流程:
首先了解一下empty_zero_page 都存放些什么东西:
Offset Type  Description
------  ----  -----------
    0 32 bytes struct screen_info, SCREEN_INFO
   ATTENTION, overlaps the following !!!
    2 unsigned short EXT_MEM_K, extended memory size in Kb (from int 0x15)
 0x20 unsigned short CL_MAGIC, commandline magic number (=0xA33F)
 0x22 unsigned short CL_OFFSET, commandline offset
   Address of commandline is calculated:
     0x90000 + contents of CL_OFFSET
   (only taken, when CL_MAGIC = 0xA33F)
 0x40 20 bytes struct apm_bios_info, APM_BIOS_INFO
 0x80 16 bytes hd0-disk-parameter from intvector 0x41
 0x90 16 bytes hd1-disk-parameter from intvector 0x46
 0xa0 16 bytes System description table truncated to 16 bytes.
   ( struct sys_desc_table_struct )
 0xb0 - 0x1df  Free. Add more parameters here if you really need them.
0x1e0 unsigned long ALT_MEM_K, alternative mem check, in Kb
0x1e8 char  number of entries in E820MAP (below)
0x1f1 char  size of setup.S, number of sectors
0x1f2 unsigned short MOUNT_ROOT_RDONLY (if !=0)
0x1f4 unsigned short size of compressed kernel-part in the
   (b)zImage-file (in 16 byte units, rounded up)
0x1f6 unsigned short swap_dev (unused AFAIK)
0x1f8 unsigned short RAMDISK_FLAGS
0x1fa unsigned short VGA-Mode (old one)
0x1fc unsigned short ORIG_ROOT_DEV (high=Major, low=minor)
0x1ff char  AUX_DEVICE_INFO
0x200 short jump to start of setup code aka "reserved" field.
0x202 4 bytes  Signature for SETUP-header, ="HdrS"
0x206 unsigned short Version number of header format
   Current version is 0x0201...
0x208 8 bytes  (used by setup.S for communication with boot loaders,
    look there)
0x210 char  LOADER_TYPE, = 0, old one
   else it is set by the loader:
   0xTV: T=0 for LILO
    1 for Loadlin
    2 for bootsect-loader
    3 for SYSLINUX
    4 for ETHERBOOT
    V = version
0x211 char  loadflags:
   bit0 = 1: kernel is loaded high (bzImage)
   bit7 = 1: Heap and pointer (see below) set by boot
      loader.
0x212 unsigned short (setup.S)
0x214 unsigned long KERNEL_START, where the loader started the kernel
0x218 unsigned long INITRD_START, address of loaded ramdisk image
0x21c unsigned long INITRD_SIZE, size in bytes of ramdisk image
0x220 4 bytes  (setup.S)
0x224 unsigned short setup.S heap end pointer
0x2d0 - 0x600  E820MAP
0x800 string, 2K max COMMAND_LINE, the kernel commandline as
   copied using CL_OFFSET.
   Note: this will be copied once more by setup.c
   into a local buffer which is only 256 bytes long.
   ( #define COMMAND_LINE_SIZE 256 )

loader_ok:
# Get memory size (extended mem, kB)
 xorl %eax, %eax
 movl %eax, (0x1e0)
#ifndef STANDARD_MEMORY_BIOS_CALL
 movb %al, (E820NR)  # E820NR=0x1e8 number of entries in E820MAP
# Try three different memory detection schemes.  First, try
# e820h, which lets us assemble a memory map, then try e801h,
# which returns a 32-bit memory size, and finally 88h, which
# returns 0-64m
# method E820H:
# the memory map from hell.  e820h returns memory classified into
# a whole bunch of different types, and allows memory holes and
# everything.  We scan through this memory map and build a list
# of the first 32 memory areas, which we return at [E820MAP].
# This is documented at http://www.teleport.com/~acpi/acpihtml/topic245.htm
#define SMAP  0x534d4150
meme820:
 xorl %ebx, %ebx   # continuation counter
 movw $E820MAP, %di   # point into the whitelist
      # so we can have the bios
      # directly write into it.
jmpe820:
 movl $0x0000e820, %eax  # e820, upper word zeroed
 movl $SMAP, %edx   # ascii 'SMAP'
 movl $20, %ecx   # size of the e820rec
 pushw %ds    # data record.
 popw %es
 int $0x15    # make the call
 jc bail820    # fall to e801 if it fails
 cmpl $SMAP, %eax   # check the return is `SMAP'
 jne bail820    # fall to e801 if it fails
# cmpl $1, 16(%di)   # is this usable memory?
# jne again820
 # If this is usable memory, we save it by simply advancing %di by
 # sizeof(e820rec).
 #
good820:
 movb (E820NR), %al   # up to 32 entries
 cmpb $E820MAX, %al
 jnl bail820
 incb (E820NR)
 movw %di, %ax
 addw $20, %ax
 movw %ax, %di
again820:
 cmpl $0, %ebx   # check to see if
 jne jmpe820    # %ebx is set to EOF
bail820:

通过上面的汇编指令,就把可用内存的Entry描述块顺序放到了empty_zero_page的
0x2d0 - 0x600  E820MAP处.那么计算内存大小也就不困难了.
 

Int 15/AX=E801h 
reference:http://www.ctyme.com/intr/rb-1739.htm

Phoenix BIOS v4.0 - GET MEMORY SIZE FOR >64M CONFIGURATIONS

AX = E801h

Return:
CF clear if successfulAX = extended memory between 1M and 16M, in K (max 3C00h = 15MB)BX = extended memory above 16M, in 64K blocksCX = configured memory 1M to 16M, in KDX = configured memory above 16M, in 64K blocksCF set on error

Notes: Supported by the A03 level (6/14/94) and later XPS P90 BIOSes, as well as
the Compaq Contura, 3/8/93 DESKPRO/i, and 7/26/93 LTE Lite 386 ROM BIOS.
Supported by AMI BIOSes dated 8/23/94 or later. On some systems, the BIOS returns
AX=BX=0000h; in this case, use CX and DX instead of AX and BX. This interface is
used by Windows NT 3.1, OS/2 v2.11/2.20, and is used as a fall-back by newer
versions if AX=E820h is not supported. This function is not used by MS-DOS 6.0
HIMEM.SYS when an EISA machine (for example with parameter /EISA)
(see also MEM F000h:FFD9h), or no Compaq machine was detected, or parameter
/NOABOVE16 was given.
 
 

 
 
meme801:
 stc     # fix to work around buggy
 xorw %cx,%cx    # BIOSes which dont clear/set
 xorw %dx,%dx    # carry on pass/error of
      # e801h memory size call
      # or merely pass cx,dx though
      # without changing them.
 movw $0xe801, %ax
 int $0x15
 jc mem88
 cmpw $0x0, %cx   # Kludge to handle BIOSes
 jne e801usecxdx   # which report their extended
 cmpw $0x0, %dx   # memory in AX/BX rather than
 jne e801usecxdx   # CX/DX.  The spec I have read
 movw %ax, %cx   # seems to indicate AX/BX
 movw %bx, %dx   # are more reasonable anyway...
e801usecxdx:
 andl $0xffff, %edx   # clear sign extend
 shll $6, %edx   # and go from 64k to 1k chunks
 movl %edx, (0x1e0)   # store extended memory size
 andl $0xffff, %ecx   # clear sign extend
  addl %ecx, (0x1e0)   # and add lower memory into
      # total size.

 

原创粉丝点击