今天我們要談mem_size();這ㄍroutine;還記得上一章我們已經呼叫完int 15h ax=e820h;接下來我們介紹2ㄍstruct:來將我們呼叫15h中斷所得到ㄉ資料儲存到這裡來
struct mem_info_t {
unsigned long e88_mem_k; /* 0x00呼叫int15h時 eax=e88h,結果存放於此 */
unsigned long e801_mem_k; /* 0x04呼叫int15h時 eax=e801h,結果存放於此 */
unsigned long e820_nr; /* 0x08呼叫int15h時 eax=e820h,e820map總數存放於此 */
struct e820entry e820[E820MAX]; /* 0x0c 開始存放以20bytes為單位的e820 的structure*/
/* 0x28c此address是最多32個structure的end位址 */
};
struct e820entry {
/*此結構專門用來存放呼叫int15h時 eax=e820h時所得到的資訊,以便以c語言來處理這些資料*/
unsigned long long addr; /* start of memory segment long long是8個bytes */
unsigned long long size; /* size of memory segment long long是8個bytes */
unsigned long type; /* type of memory segment long是4個bytes 以上便是一個20byte的資料結構*/
};
主程序呼叫子程序以後以”=>”這個符號來表示呼叫由以上兩個structure來說明下面的程式架構: Init()=>query_pcbios()因此進入head.S並且切換cpu進入real mode,執行int15h中斷eax=e820h,因此獲得
memory map數量,最多32個,其實只有3個到5個;依照你所插入ㄉ記憶體容量及各家主機板BIOS實作方法不同而定。接著Init()=>mem_size()並將memory map配置給e820entry。 然後mem_size()=>memsize_bios(0)=>memsize_820(0)=>sanitize_e820_map(e820, nm, e820_nr, res)。
此sanitize_e820_map就是整理所有memory map的routine(他(這ㄍROUTINE)比較繁雜,我都看不下去)。在此先說明memsize_bios(),它只是去判斷我們是透過什麼方式取得memory map,我們都知道目前應該都會是query_pcbios()來取得,所以代入參數0。
至於memsize_820(res)也是代入0為參數,那麼此routine做了些什麼,我們來看看:
static void memsize_820(int res) {
int i, n, nr;
struct e820entry nm[E820MAX];
/* Clean up, adjust and copy the BIOS-supplied E820-map. */
/* If the res arg is true reclassify reserved memory as E820_RAM */
nr = sanitize_e820_map(e820, nm, e820_nr, res);
/* If there is not a good 820 map use the BIOS 801/88 info */
if (nr <> E820MAX) {
memsize_801();
return;
}
unsigned long e88_mem_k; /* 0x00呼叫int15h時 eax=e88h,結果存放於此 */
unsigned long e801_mem_k; /* 0x04呼叫int15h時 eax=e801h,結果存放於此 */
unsigned long e820_nr; /* 0x08呼叫int15h時 eax=e820h,e820map總數存放於此 */
struct e820entry e820[E820MAX]; /* 0x0c 開始存放以20bytes為單位的e820 的structure*/
/* 0x28c此address是最多32個structure的end位址 */
};
struct e820entry {
/*此結構專門用來存放呼叫int15h時 eax=e820h時所得到的資訊,以便以c語言來處理這些資料*/
unsigned long long addr; /* start of memory segment long long是8個bytes */
unsigned long long size; /* size of memory segment long long是8個bytes */
unsigned long type; /* type of memory segment long是4個bytes 以上便是一個20byte的資料結構*/
};
主程序呼叫子程序以後以”=>”這個符號來表示呼叫由以上兩個structure來說明下面的程式架構: Init()=>query_pcbios()因此進入head.S並且切換cpu進入real mode,執行int15h中斷eax=e820h,因此獲得
memory map數量,最多32個,其實只有3個到5個;依照你所插入ㄉ記憶體容量及各家主機板BIOS實作方法不同而定。接著Init()=>mem_size()並將memory map配置給e820entry。 然後mem_size()=>memsize_bios(0)=>memsize_820(0)=>sanitize_e820_map(e820, nm, e820_nr, res)。
此sanitize_e820_map就是整理所有memory map的routine(他(這ㄍROUTINE)比較繁雜,我都看不下去)。在此先說明memsize_bios(),它只是去判斷我們是透過什麼方式取得memory map,我們都知道目前應該都會是query_pcbios()來取得,所以代入參數0。
至於memsize_820(res)也是代入0為參數,那麼此routine做了些什麼,我們來看看:
static void memsize_820(int res) {
int i, n, nr;
struct e820entry nm[E820MAX];
/* Clean up, adjust and copy the BIOS-supplied E820-map. */
/* If the res arg is true reclassify reserved memory as E820_RAM */
nr = sanitize_e820_map(e820, nm, e820_nr, res);
/* If there is not a good 820 map use the BIOS 801/88 info */
if (nr <> E820MAX) {
memsize_801();
return;
}
/* Build the memory map for testing */
n = 0;
for ( i=0 ; ( i < nr ) ; i++ ) { if (nm[i].type == E820_RAM) { unsigned long long start; unsigned long long end; start = nm[i].addr; end = start + nm[i].size;
/* Don't ever use memory between 640 and 1024k */
if (start > RES_START && start < RES_END){
if (end < RES_END){
continue;
}
start = RES_END;
}
if ( end > RES_START && end < RES_END){
end = RES_START;
}
此顏色區域目的是要避開640k~1024k因此只要任何memory map 有涵蓋此區域其start或end就會被設定到640k為end或設定1024k 為start。(這部分是dos作業系統及bios專用空間,當然也包括我們程式要做顯示畫面0xb8000到0xb8fff這塊記憶體,所以這裡測試程式永遠都不會來測這一小塊。)
v->pmap[n].start = (start + 4095) >> 12;
v->pmap[n].end = end >> 12;
v->test_pages += v->pmap[n].end - v->pmap[n].start;
n++;
/*pmap+0xfff(4095)只是作4k為單位前的無條件進位。*/
n = 0;
for ( i=0 ; ( i < nr ) ; i++ ) { if (nm[i].type == E820_RAM) { unsigned long long start; unsigned long long end; start = nm[i].addr; end = start + nm[i].size;
/* Don't ever use memory between 640 and 1024k */
if (start > RES_START && start < RES_END){
if (end < RES_END){
continue;
}
start = RES_END;
}
if ( end > RES_START && end < RES_END){
end = RES_START;
}
此顏色區域目的是要避開640k~1024k因此只要任何memory map 有涵蓋此區域其start或end就會被設定到640k為end或設定1024k 為start。(這部分是dos作業系統及bios專用空間,當然也包括我們程式要做顯示畫面0xb8000到0xb8fff這塊記憶體,所以這裡測試程式永遠都不會來測這一小塊。)
v->pmap[n].start = (start + 4095) >> 12;
v->pmap[n].end = end >> 12;
v->test_pages += v->pmap[n].end - v->pmap[n].start;
n++;
/*pmap+0xfff(4095)只是作4k為單位前的無條件進位。*/
/*v->pmap[n].end - v->pmap[n].start//便是求算出以4k為單位的總頁數。*/
}
else {
/* If this is reserved memory starting at the top
* of memory then don't count it as reserved, since
* it is very unlikely to be real memory.
*/
if (nm[i].addr <>reserved_pages += nm[i].size >> 12 }
}
v->msegs = n;
if (res) { cprint(LINE_INFO, COL_MMAP, "e820-All"); }
else { cprint(LINE_INFO, COL_MMAP, "e820-Std"); } }
●以上程式碼要看n平方次才會懂ㄉ,尤其是那ㄍ sanitize_e820_map●
}
else {
/* If this is reserved memory starting at the top
* of memory then don't count it as reserved, since
* it is very unlikely to be real memory.
*/
if (nm[i].addr <>reserved_pages += nm[i].size >> 12 }
}
v->msegs = n;
if (res) { cprint(LINE_INFO, COL_MMAP, "e820-All"); }
else { cprint(LINE_INFO, COL_MMAP, "e820-Std"); } }
●以上程式碼要看n平方次才會懂ㄉ,尤其是那ㄍ sanitize_e820_map●