前回の記事で、WCELDRにネットワークアダプタのライブラリを追加してみました。
残念ながら、そのままWCELDRをビルドしても、
リンクフェーズでエラーとなりました。
どんなエラーかというと、
『unresolved external symbol_OALStall referenced in ...』
つまり、コンパイルフェーズで生成したオブジェクトの中に、
OALStall関数が見当たらないということです。
もともと、追加したネットワークアダプタのライブラリは、
KITL用に作成されたものです。
で、ライブラリ内にOAL(OEM Adapted Layer)が提供する関数を使用しているのですが、
WCELDRはOSが起動する前のブート用のコードなので、
そのOALの関数が含まれていないんですね。
なので、この関数を何かしら実装する必要があります。
不足しているOALStallという関数が何をする処理かというと、
パラメータで指定された時間(単位はマイクロ秒)だけ
Waitする処理です。
AM79C973のライブラリのソースコードを確認すると、
いろんな箇所でこの関数をコールしてますね。
このデバイスの特性上、数10マイクロ秒で状態が変化するのを
待ったりしているんでしょうね。
じゃあ、どうやってこの関数を実装するかというと、
WCELDR内に既に実装されているソースコードを活用しようと思います。
WCELDRのBLDRに、init.cというソースコードがあり、
その中に
void
OEMBootStall(
uint32_t delay
)
{
uint32_t eax, ebx, ecx, edx, esi, edi;
eax = 0x8600;
ecx = (delay >> 16) & 0xFFFF;
edx = (delay >> 0) & 0xFFFF;
BootBiosInt15(&eax, &ebx, &ecx, &edx, &esi, &edi);
}
という実装があります。
この処理は、BIOSのWait機能(割り込みルーチン15H function 86H)を呼び出します。
ちょうどいい関数ですね(笑)。
OALStallの関数インターフェースは、
%WINCEROOT%¥platform¥common¥src¥inc¥oal_timer.h
に定義があるので、この定義通りの関数を作成し、
関数内でOEMBootStallを呼び出すようにしてやればよさそうです。
ライブラリのソースコードやinit.cになるべく手を入れたくないので、
別途oalfunc.cというファイルをWCELDRのBLDRのフォルダ内に作成し、
中に以下のような処理を実装してみました。
#include "bldr.h"
extern void OEMBootStall( uint32_t delay );
VOID OALStall( UINT32 uSecs )
{
OEMBootStall( uSecs );
}
このファイルがコンパイルされるように、
consoleおよびserialフォルダ内のsourcesファイルの
SOURCESパラメータにoalfunc.cを追記します。
そして再度buildし、エラーが解消されることを確認してください。
これでVMWare Player用のWCELDRができた(はず)なので(笑)、
次回をこれを実際にVMWareでロードし、ネットワークブート可能かを
確認したいと思います。
残念ながら、そのままWCELDRをビルドしても、
リンクフェーズでエラーとなりました。
どんなエラーかというと、
『unresolved external symbol_OALStall referenced in ...』
つまり、コンパイルフェーズで生成したオブジェクトの中に、
OALStall関数が見当たらないということです。
もともと、追加したネットワークアダプタのライブラリは、
KITL用に作成されたものです。
で、ライブラリ内にOAL(OEM Adapted Layer)が提供する関数を使用しているのですが、
WCELDRはOSが起動する前のブート用のコードなので、
そのOALの関数が含まれていないんですね。
なので、この関数を何かしら実装する必要があります。
不足しているOALStallという関数が何をする処理かというと、
パラメータで指定された時間(単位はマイクロ秒)だけ
Waitする処理です。
AM79C973のライブラリのソースコードを確認すると、
いろんな箇所でこの関数をコールしてますね。
このデバイスの特性上、数10マイクロ秒で状態が変化するのを
待ったりしているんでしょうね。
じゃあ、どうやってこの関数を実装するかというと、
WCELDR内に既に実装されているソースコードを活用しようと思います。
WCELDRのBLDRに、init.cというソースコードがあり、
その中に
void
OEMBootStall(
uint32_t delay
)
{
uint32_t eax, ebx, ecx, edx, esi, edi;
eax = 0x8600;
ecx = (delay >> 16) & 0xFFFF;
edx = (delay >> 0) & 0xFFFF;
BootBiosInt15(&eax, &ebx, &ecx, &edx, &esi, &edi);
}
という実装があります。
この処理は、BIOSのWait機能(割り込みルーチン15H function 86H)を呼び出します。
ちょうどいい関数ですね(笑)。
OALStallの関数インターフェースは、
%WINCEROOT%¥platform¥common¥src¥inc¥oal_timer.h
に定義があるので、この定義通りの関数を作成し、
関数内でOEMBootStallを呼び出すようにしてやればよさそうです。
ライブラリのソースコードやinit.cになるべく手を入れたくないので、
別途oalfunc.cというファイルをWCELDRのBLDRのフォルダ内に作成し、
中に以下のような処理を実装してみました。
#include "bldr.h"
extern void OEMBootStall( uint32_t delay );
VOID OALStall( UINT32 uSecs )
{
OEMBootStall( uSecs );
}
このファイルがコンパイルされるように、
consoleおよびserialフォルダ内のsourcesファイルの
SOURCESパラメータにoalfunc.cを追記します。
そして再度buildし、エラーが解消されることを確認してください。
これでVMWare Player用のWCELDRができた(はず)なので(笑)、
次回をこれを実際にVMWareでロードし、ネットワークブート可能かを
確認したいと思います。