顯示具有 Edk2 標籤的文章。 顯示所有文章
顯示具有 Edk2 標籤的文章。 顯示所有文章

2015年3月26日 星期四

C Library(Module) Loader for UEFI Lua



require("mylib")    // load mylib.efi or mylib.so or mylib.dll

本篇學習如何建立在Uefi 下可供Lua載入的library

試圖讓library能由Lua C Loader 載入

關鍵檔案在src/loadlib.c


LUA_USE_DLOPEN :for linux *.so


LUA_DL_DLL :for windows *.dll




/*

119 ** {========================================================================

120 ** This is an implementation of loadlib based on the dlfcn interface.

121 ** The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD,

122 ** NetBSD, AIX 4.2, HPUX 11, and  probably most other Unix flavors, at least

123 ** as an emulation layer on top of native functions.

124 ** =========================================================================

125 */
126 
127 #include <dlfcn.h>
128 
129 static void ll_unloadlib (void *lib) {
130   dlclose(lib);
131 }
132 
133 
134 static void *ll_load (lua_State *L, const char *path, int seeglb) {
135   void *lib = dlopen(path, RTLD_NOW | (seeglb ? RTLD_GLOBAL : RTLD_LOCAL));
136   if (lib == NULL) lua_pushstring(L, dlerror());
137   return lib;
138 }
139 
140 
141 static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
142   lua_CFunction f = (lua_CFunction)dlsym(lib, sym);
143   if (f == NULL) lua_pushstring(L, dlerror());
144   return f;
145 }
146 
147 /* }====================================================== */
148 
149 


222 #undef LIB_FAIL
223 #define LIB_FAIL    "absent"
224 
225 
226 #define DLMSG   "dynamic libraries not enabled; check your Lua installation"
227 
228 
229 static void ll_unloadlib (void *lib) {
230   (void)(lib);  /* not used */
231 }
232 
233 
234 static void *ll_load (lua_State *L, const char *path, int seeglb) {
235   (void)(path); (void)(seeglb);  /* not used */
236   lua_pushliteral(L, DLMSG);
237   return NULL;
238 }
239 
240 
241 static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
242   (void)(lib); (void)(sym);  /* not used */
243   lua_pushliteral(L, DLMSG);
244   return NULL;
245 }


初步判斷整個過程是利用dlopen 及 LoadLibraryEx的加載過程.......

疑問: Uefi 有Dynamic Load Library架構嗎?好像是沒有,載入Library有重定位問題,UEFI 可由載入的Application or Driver 中,對應出所要的Function ?要將Library以UEFI Driver 常駐形式存在,且初始化時,要建立FunctionName及FunctionAddress 對應關係


static void ll_unloadlib (void *lib)

static void *ll_load (lua_State *L, const char *path, int seeglb)

static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym)


在UEFI 下實現構想如下:

1.建立 EFI_LUA_DLL_PROTOCOL,用於Function name查找
2.於ll_load時載入 Lua Module Uefi Driver
3.於ll_unloadlib時卸載 Lua Module Uefi Driver
4.於ll_sym時call method 取得Function Address


 static int ll_loadfunc (lua_State *L, const char *path, const char *sym) {
287   void *reg = ll_checkclib(L, path);  /* check loaded C libraries */
288   if (reg == NULL) {  /* must load library? */
289     reg = ll_load(L, path, *sym == '*');
290     if (reg == NULL) return ERRLIB;  /* unable to load library */
291     ll_addtoclib(L, path, reg);
292   }
293   if (*sym == '*') {  /* loading only library (no function)? */
294     lua_pushboolean(L, 1);  /* return 'true' */
295     return 0;  /* no errors */
296   }
297   else {
298     lua_CFunction f = ll_sym(L, reg, sym);
299     if (f == NULL)
300       return ERRFUNC;  /* unable to find function */
301     lua_pushcfunction(L, f);  /* else create new function */
302     return 0;  /* no errors */
303   }
304 }


print(package.path)
require("hello")

(收工)

2015年3月24日 星期二

UEFI Serial I/O Protocol


UEFI Spec. Ver.2.4

GUID
#define EFI_SERIAL_IO_PROTOCOL_GUID \
 {0xBB25CF6F,0xF1D4,0x11D2,0x9A,0x0C,0x00,0x90,\
 0x27,0x3F,0xC1,0xFD}

Revision Number
#define EFI_SERIAL_IO_PROTOCOL_REVISION 0x00010000

Protocol Interface Structure
typedef struct {
 UINT32 Revision;
 EFI_SERIAL_RESET Reset;
 EFI_SERIAL_SET_ATTRIBUTES SetAttributes;
 EFI_SERIAL_SET_CONTROL_BITS SetControl;
 EFI_SERIAL_GET_CONTROL_BITS GetControl;
 EFI_SERIAL_WRITE Write;
 EFI_SERIAL_READ Read;
 SERIAL_IO_MODE *Mode;
} EFI_SERIAL_IO_PROTOCOL;

Parameters
Revision The revision to which the EFI_SERIAL_IO_PROTOCOL
adheres. All future revisions must be backwards compatible. If a
future version is not back wards compatible, it is not the same
GUID.
Reset Resets the hardware device.
SetAttributes Sets communication parameters for a serial device. These
include the baud rate, receive FIFO depth, transmit/receive time
out, parity, data bits, and stop bit attributes.
SetControl Sets the control bits on a serial device. These include Request to
Send and Data Terminal Ready.
GetControl Reads the status of the control bits on a serial device. These
include Clear to Send, Data Set Ready, Ring Indicator, and
Carrier Detect.
Write Sends a buffer of characters to a serial device.
Read Receives a buffer of characters from a serial device.
Mode Pointer to SERIAL_IO_MODE data. Type SERIAL_IO_MODE
is defined in “Related Definitions” below.


Related Definitions

//*******************************************************
// SERIAL_IO_MODE
//*******************************************************
typedef struct {
UINT32 ControlMask;
 // current Attributes
 UINT32 Timeout;
 UINT64 BaudRate;
 UINT32 ReceiveFifoDepth;
 UINT32 DataBits;
 UINT32 Parity;
 UINT32 StopBits;
} SERIAL_IO_MODE;


//*******************************************************
// CONTROL BITS
//*******************************************************
// Read Only
#define EFI_SERIAL_CLEAR_TO_SEND 0x0010
#define EFI_SERIAL_DATA_SET_READY 0x0020
#define EFI_SERIAL_RING_INDICATE 0x0040
#define EFI_SERIAL_CARRIER_DETECT 0x0080
#define EFI_SERIAL_INPUT_BUFFER_EMPTY 0x0100   // See if the Receive FIFO is empty.
#define EFI_SERIAL_OUTPUT_BUFFER_EMPTY 0x0200 // See if the Transmit FIFO is empty

// Write Only
#define EFI_SERIAL_REQUEST_TO_SEND 0x0002
#define EFI_SERIAL_DATA_TERMINAL_READY 0x0001

// Read Write
#define EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE 0x1000
#define EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE 0x2000
#define EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE 0x4000


串列埠的原理與應用


1.可透過GetControl function查看EFI_SERIAL_INPUT_BUFFER_EMPTY決定目前有無資料被接收,若有資料,則利用Read function讀進來

ReceiveFifoDepth The requested depth of the FIFO on the receive side of the serial
interface. A ReceiveFifoDepth value of 0 will use the
device’s default FIFO depth

Timeout The requested time out for a single character in microseconds.
This timeout applies to both the transmit and receive side of the
interface. A Timeout value of 0 will use the device’s default
time out value.

設定組態
  EFI_PARITY_TYPE         Parity=NoParity;
  EFI_STOP_BITS_TYPE      StopBits=OneStopBit;
  UINTN                   BaudRate=9600;
  UINTN                   DataBits=8;

 Status = SerialIo->SetAttributes (
                              SerialIo,
                              (UINT64) BaudRate, //9600
                              0, //use default
                              0, //use default
                              Parity, // N 
                              (UINT8) DataBits, //8
                              StopBits //1
                             );

檢查有無資料進來
  UINT32 SerialControl;

  Status = SerialIo->GetControl (
                 SerialIo,
                 &SerialControl);
  if (!EFI_ERROR (Status)) {
    if ((SerialControl & EFI_SERIAL_INPUT_BUFFER_EMPTY) != 0) {
      Status = EFI_NOT_READY;
    } else {
      Status = EFI_SUCCESS;
    }
  }




2015年3月20日 星期五

Use Serial Device to control something under UEFI Shell Environment


因為有個構想,想在UEFI Shell 下控制各類的Serial Device,所以對此稍微做了以下研究........

相關資料:
http://en.wikipedia.org/wiki/Serial_port
http://en.wikipedia.org/wiki/Universal_asynchronous_receiver/transmitter
http://en.wikipedia.org/wiki/FTDI
http://www.crashcourse.ca/wiki/index.php/USB/serial_driver_and_pl2303
http://www.intel.eu/content/dam/doc/product-specification/efi-v1-10-specification.pdf
http://www.uefi.org/sites/default/files/resources/UEFI_Shell_Spec_2_0.pdf



Serial Device可能有下列幾種介面:
1. ISA
2. PCI
3. USB



EFI Spec V1.10  "10.12 Serial I/O Protocol" 有定義SerialIO Protocol相關資訊

typedef struct {
 UINT32 Revision;
 EFI_SERIAL_RESET Reset;
 EFI_SERIAL_SET_ATTRIBUTES SetAttributes;
 EFI_SERIAL_SET_CONTROL_BITS SetControl;
 EFI_SERIAL_GET_CONTROL_BITS GetControl;
 EFI_SERIAL_WRITE Write;
 EFI_SERIAL_READ Read;
 SERIAL_IO_MODE *Mode;
} SERIAL_IO_INTERFACE; 




首先,先在UEFI Shell 下, 執行sermode , 得到如下結果 :
( sermode command 請參照 UEFI Shell Spec.)
Shell> sermode
sermode: No serial ports present

Shell>


看來相關的UEFI Driver ,沒有掛起來,得要自己Build ㄧ下code才行........

根據我Mainboard的COM Port設定, 估計得Build IsaSerialIoDxe module , 來源從EDK2。
試了一下,還是不行,仔細再看了ㄧ下code, 還需要Build IsaIoDxe module.......
Build好之後再試試看,結果終於有反應了,顯示如下,但不確定是否會動作正常,需再進一步驗證。

fs0:\Efi\tools> load IsaIoDxe.efi
load Image fs0:\Efi\tools\IsaIoDxe.efi loaded at B84CD000 - Success

fs0:\Efi\tools> load IsaSerialDxe.efi
load Image fs0:\Efi\tools\IsaSerialDxe.efi loaded at B84C4000 - Success

fs0:\Efi\tools> sermode
147(AD548D18) - (115200, N, 8, 1)

fs0:\Efi\tools> sermode 147 9600 N 8 1,
sermode: Mode set on handle AD548D18

fs0:\Efi\tools> sermode 
147(AD548D18) - (9600, N, 8, 1)

fs0:\Efi\tools>

在寫個測試程式前,先來找找看UEFI 有沒有Usb serial device driver.
透過Google找到了下列描述:

"Status: Completed (For FTDI). Available at OptionRomPkg/Bus/Usb/FtdiUsbSerialDxe."

再搜尋了一下,發現市售常用的USB-serial 晶片有下列幾款:
1.FT232R
2.PL2303
3.CH340g/340T/340R
4.CP210x


目前我手上有幾款USB serial device, ID資訊如下:

CH340T => ID 1a86:7523 QinHeng Electronics HL-340 USB-Serial adapter
PL2303 => ID 067b:2303 Prolific Technology, Inc. PL2303 Serial Port
FT232R => ID 0403:6001 Future Technology Devices International, Ltd FT232 USB-Serial (UART) IC


針對FT232R Driver 修改如下:
  //
  // add code to set trigger time based on baud rate
  // setting to 0.5s for now
  //
  gBS->SetTimer (
         UsbSerialDevice->PollingLoop,
         TimerPeriodic,
         EFI_TIMER_PERIOD_MILLISECONDS (100) //從500修改成100
         );


測試結果FT232R Usb-Serial 可動作正常,傳輸資料也OK...


硬體不一樣,當然行為模式也不一樣,至於PL2303, CH340 , CP2102 的UEFI Driver 網路上還沒找到現成的,只好等有時間再來嘗試Porting了.........


Download : FtdiUsbSerialDxe.efi (64bits Version)
Download : IsaSerialIoDxe (64bits Version)
Download : IsaIoDxe (64bits Version)