2009年7月3日金曜日

query_edd

main関数もようやく終盤、今回は「query_edd」を見ていきます。
EDDというのは「Enhanced Disk Drive」の略で、4GBを超えたメモリアクセスを可能にする仕組みです。

arch/x86/boor/edd.c
======
void query_edd(void)
{
/* ~省略(変数宣言)~*/

/* 起動オプションでeddのON/OFFが指定されているか? */
if (cmdline_find_option("edd", eddarg, sizeof eddarg) > 0) {
/* ~省略(チェック結果で変数更新)~*/
}

/* "quiet"オプションが指定されているか? */
be_quiet = cmdline_find_option_bool("quiet");

edp    = boot_params.eddbuf;
mbrptr = boot_params.edd_mbr_sig_buffer;

/* EDD拡張いらないならおしまい */
if (!do_edd)
return;

/* "quiet"指定されていなければメッセージ出力 */
if (!be_quiet)
printf("Probing EDD (edd=off to disable)... ");

/* デバイスをチェックする */
for (devno = 0x80; devno < 0x80+EDD_MBR_SIG_MAX; devno++) { /* EDD情報を取得 */ if (!get_edd_info(devno, &ei)     && boot_params.eddbuf_entries < EDDMAXNR) { memcpy(edp, &ei, sizeof ei); edp++; /* ここでboot_params.eddbufにEDD情報が格納される */ boot_params.eddbuf_entries++; } if (do_mbr && !read_mbr_sig(devno, &ei, mbrptr++)) boot_params.edd_mbr_sig_buf_entries = devno-0x80+1; } if (!be_quiet) printf("ok\n"); }

======

query_eddの中で呼んでいる「get_edd_info」「read_mbr_sig」を見てみます。
まずは「get_edd_info」から。

======
static int get_edd_info(u8 devno, struct edd_info *ei)
{
/*~省略~*/

/* EDD情報を取得 */
ax = 0x4100;
bx = EDDMAGIC1;
dx = devno;
asm("pushfl; stc; int $0x13; setc %%al; popfl"
    : "+a" (ax), "+b" (bx), "=c" (cx), "+d" (dx)
    : : "esi", "edi");

/*~省略~*/

/* EDDバージョン、機能セットの格納しておく */
ei->device  = devno;
ei->version = ax >> 8; /* EDD version number */
ei->interface_support = cx; /* EDD functionality subsets */

/* 拡張デバイスパラメータを取得してei->paramsに格納する */
ei->params.length = sizeof(ei->params);
ax = 0x4800;
dx = devno;
asm("pushfl; int $0x13; popfl"
    : "+a" (ax), "+d" (dx), "=m" (ei->params)
    : "S" (&ei->params)
    : "ebx", "ecx", "edi");

/* レガシーなCHS(Cylinder, Head, Sector)情報を取得 */
ax = 0x0800;
dx = devno;
di = 0;
asm("pushw %%es; "
    "movw %%di,%%es; "
    "pushfl; stc; int $0x13; setc %%al; popfl; "
    "popw %%es"
    : "+a" (ax), "=b" (bx), "=c" (cx), "+d" (dx), "+D" (di)
    : : "esi");

if ((u8)ax == 0) {
ei->legacy_max_cylinder = (cx >> 8) + ((cx & 0xc0) << 2); ei->legacy_max_head = dx >> 8;
ei->legacy_sectors_per_track = cx & 0x3f;
}

return 0;
}

======

次に「read_mbr_sig」。

======
static u32 read_mbr_sig(u8 devno, struct edd_info *ei, u32 *mbrsig)
{
/*~省略~*/

/* セクタサイズが未設定なら512にしておく */
sector_size = ei->params.bytes_per_sector;
if (!sector_size)
sector_size = 512; /* Best available guess */

/* ヒープ上のアラインをセット */
buf_base = (ds() << 4) + (u32)&_end; mbr_base = (buf_base+sector_size-1) & ~(sector_size-1); mbrbuf_ptr = _end + (mbr_base-buf_base); mbrbuf_end = mbrbuf_ptr + sector_size; /*~省略~*/ /* MBRを読み込む */ if (read_mbr(devno, mbrbuf_ptr)) return -1; *mbrsig = *(u32 *)&mbrbuf_ptr[EDD_MBR_SIG_OFFSET]; return 0; }

======

というわけで、「query_edd」とそのサブ関数を見てきたわけですが中心となっているのは「get_edd_info」でBIOS関数を使ってEDD情報を取ってきてブートパラメータ構造体に格納する、といういつもの流れです。

0 件のコメント:

コメントを投稿