簡單來說,如果很久以前曾在 Linux or Unix 下寫過 socket 程式,那我想這就不是一件很難的事,只要注意一些 header 檔案的位置跟傳統的不一樣即可。
從上圖可以得知,要在 UEFI Shell 下使用網路,需具備 4 要件:
1. 要有網卡。
2. 要有 UNDI driver。
3. 載入 Simple Network Protocol。
4. 載入 TCP / IP Stack。
註:從 Intel 的文件 "UEFI Driver Development Guide for Network Boot Devices" 來看,SNP 和 TCP / IP Stack 中間似乎還有一層 MNP ( Managed Network Protocol ),不過這邊我們可以先忽略它。
以我的小電腦來說,除了 Simple Network Protocol 以外,其餘皆已內建,故我從 UDK2014 code base 中 build 出此 driver 即可﹝C:\edk2-UDK2014\MdeModulePkg\Universal\Network﹞,接著開機時,使用 "load" command 載入 driver,便可以順利使用 "ifconfig" command 取得 IP。
再來就是跟以前撰寫 socket 程式一樣,呼叫 socket, connect, send, close 等函式完成想要完成的工作,底下為 Client 端發送封包的例子。
#include <netinet/in.h>
#include <sys/EfiSysCall.h>
#include <sys/socket.h>
#include <arpa/inet.h>
int testTCPSocket(char *serverIP, int serverPort)
{
int rc;
int sock;
struct sockaddr_in v4;
char data[1024];
size_t sentBytes;
size_t sendStrLen;
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == -1)
{
printf("init socket error\n");
return -1;
}
memset(&v4, 0x00, sizeof(v4));
v4.sin_len = sizeof(v4);
v4.sin_family = AF_INET;
v4.sin_addr.s_addr = inet_addr(serverIP);
v4.sin_port = htons(serverPort);
rc = connect(sock, (struct sockaddr*)&v4, sizeof(v4));
if (rc == -1)
{
printf("connect() failed (%d)\n", rc);
//return -1;
}
printf("input string to send or 'q' to exit connection\n");
while (1)
{
memset(data, 0x00, sizeof(data));
fgets(data, sizeof(data) - 1, stdin);
if (data[0] == 'q')
{
printf("ready to exit connection\n");
break;
}
sendStrLen = strlen(data);
if (sendStrLen > 0 && sendStrLen < 1023)
{
sentBytes = send(sock, data, sendStrLen, 0);
printf("\t !!! Sent data: %s(%d) --- \n", data, sentBytes);
}
}
close(sock);
return 0;
}
沒有留言:
張貼留言