pxe_loadfile.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,697 行 · 第 1/3 页
C
1,697 行
UINT16 n;
EfiCopyMem (&n, &op[2], 2);
CredentialLen = HTONS (n) * 512;
}
}
if (CredentialLen == 0) {
BlockSize = 8192;
Status = Private->EfiBc.Mtftp (
&Private->EfiBc,
EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE,
NULL,
FALSE,
&CredentialLen,
&BlockSize,
&Private->ServerIp,
CredentialFilename,
NULL,
FALSE
);
if (EFI_ERROR (Status)) {
return Status;
}
if (CredentialLen == 0) {
//
// %%TBD -- EFI error for invalid credential
// file.
//
return EFI_PROTOCOL_ERROR;
}
}
//
// Allocate credential file buffer.
//
Status = gBS->AllocatePool (
EfiBootServicesData,
(UINTN) CredentialLen,
&CredentialBuffer
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Download credential file.
//
BlockSize = 8192;
Status = Private->EfiBc.Mtftp (
&Private->EfiBc,
EFI_PXE_BASE_CODE_TFTP_READ_FILE,
CredentialBuffer,
FALSE,
&CredentialLen,
&BlockSize,
&Private->ServerIp,
CredentialFilename,
NULL,
FALSE
);
if (EFI_ERROR (Status)) {
gBS->FreePool (CredentialBuffer);
return Status;
}
//
// Verify credentials.
//
if (PxebcBisVerify (Private, Buffer, Private->FileSize, CredentialBuffer, (UINTN) CredentialLen)) {
Status = EFI_SUCCESS;
} else {
//
// %%TBD -- An EFI error code for failing credential verification.
//
Status = EFI_PROTOCOL_ERROR;
}
gBS->FreePool (CredentialBuffer);
}
return Status;
}
STATIC
EFI_STATUS
LoadfileStart (
IN PXE_BASECODE_DEVICE *Private,
IN OUT UINT64 *BufferSize,
IN VOID *Buffer
)
/*++
Routine Description:
Start PXE DHCP. Get DHCP and proxyDHCP information.
Display remote boot menu and prompt. Select item from menu.
Arguments:
Private - Pointer to PxeBc interface
BufferSize - Pointer to download buffer size
Buffer - Pointer to download buffer
Returns:
EFI_SUCCESS -
EFI_NOT_READY -
--*/
{
EFI_PXE_BASE_CODE_MODE *PxeBcMode;
EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
EFI_SIMPLE_NETWORK_MODE *SnpMode;
EFI_STATUS Status;
VOID *RxBuf;
DEBUG ((EFI_D_WARN, "\nLoadfileStart() Enter."));
//
// Try to start BaseCode, for now only IPv4 is supported
// so don't try to start using IPv6.
//
Status = Private->EfiBc.Start (&Private->EfiBc, FALSE);
if (EFI_ERROR (Status)) {
if (Status != EFI_ALREADY_STARTED) {
DEBUG ((EFI_D_NET, "\nLoadfileStart() Exit BC.Start() == %xh", Status));
return Status;
}
}
//
// Get pointers to PXE mode structure, SNP protocol structure
// and SNP mode structure.
//
PxeBcMode = Private->EfiBc.Mode;
Snp = Private->SimpleNetwork;
SnpMode = Snp->Mode;
//
// Display client MAC address, like 16-bit PXE ROMs
//
Aprint ("\nCLIENT MAC ADDR: ");
{
UINTN Index;
UINTN hlen;
hlen = SnpMode->HwAddressSize;
for (Index = 0; Index < hlen; ++Index) {
Aprint ("%02x ", SnpMode->CurrentAddress.Addr[Index]);
}
}
Aprint ("\nDHCP");
Status = Private->EfiBc.Dhcp (&Private->EfiBc, TRUE);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_WARN, "\nLoadfileStart() Exit BC.Dhcp() == %Xh", Status));
Aprint ("\r \r");
return Status;
}
ShowMyInfo (Private);
RxBuf = PxeBcMode->ProxyOfferReceived ? &PXE_OFFER_BUFFER : &DHCPV4_ACK_BUFFER;
#define RxBufferPtr ((DHCP_RECEIVE_BUFFER *) RxBuf)
Status = DoMenu (Private, RxBufferPtr);
if (Status == EFI_SUCCESS) {
//
// did a discovery - take info from discovery packet
//
RxBuf = &PXE_ACK_BUFFER;
} else if (Status == NO_MENU) {
//
// did not do a discovery - take info from rxbuf
//
Private->ServerIp.Addr[0] = RxBufferPtr->u.Dhcpv4.siaddr;
if (!(Private->ServerIp.Addr[0])) {
*(IPV4_ADDR *) &Private->ServerIp = *(IPV4_ADDR *) RxBufferPtr->OpAdds.PktOptAdds[OP_DHCP_SERVER_IP_IX - 1]->Data;
}
} else {
DEBUG ((EFI_D_WARN, "\nLoadfileStart() Exit DoMenu() == %Xh", Status));
return Status;
}
if (!RxBufferPtr->OpAdds.PktOptAdds[OP_DHCP_BOOTFILE_IX - 1]) {
DEBUG ((EFI_D_WARN, "\nLoadfileStart() Exit Not ready?"));
return EFI_NOT_READY;
}
//
// check for file size option sent
//
if (RxBufferPtr->OpAdds.PktOptAdds[OP_BOOT_FILE_SZ_IX - 1]) {
Private->FileSize = 512 * NTOHS (RxBufferPtr->OpAdds.PktOptAdds[OP_BOOT_FILE_SZ_IX - 1]->Data);
}
Private->BootServerReceiveBuffer = RxBufferPtr;
Status = DownloadFile (Private, BufferSize, Buffer);
DEBUG (
(EFI_D_WARN,
"\nLoadfileStart() Exit. DownloadFile() = %Xh",
Status)
);
return Status;
}
EFI_STATUS
EFIAPI
LoadFile (
IN EFI_LOAD_FILE_PROTOCOL *This,
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
IN BOOLEAN BootPolicy,
IN OUT UINTN *BufferSize,
IN OUT VOID *Buffer
)
/*++
Routine Description:
Loadfile interface for PxeBc interface
Arguments:
This - Pointer to Loadfile interface
FilePath - Not used and not checked
BootPolicy - Must be TRUE
BufferSize - Pointer to buffer size
Buffer - Pointer to download buffer or NULL
Returns:
EFI_INVALID_PARAMETER -
EFI_UNSUPPORTED -
EFI_SUCCESS -
EFI_BUFFER_TOO_SMALL -
--*/
{
LOADFILE_DEVICE *LoadfilePtr;
UINT64 TmpBufSz;
INT32 OrigMode;
INT32 OrigAttribute;
BOOLEAN RemoveCallback;
BOOLEAN NewMakeCallback;
EFI_STATUS Status;
EFI_STATUS TempStatus;
//
//
//
OrigMode = gST->ConOut->Mode->Mode;
OrigAttribute = gST->ConOut->Mode->Attribute;
RemoveCallback = FALSE;
Aprint ("Running LoadFile()\n");
//
// Resolve Warning 4 unreferenced parameter problem
//
FilePath = NULL;
//
// If either if these parameters are NULL, we cannot continue.
//
if (This == NULL || BufferSize == NULL) {
DEBUG ((EFI_D_WARN, "\nLoadFile() This or BufferSize == NULL"));
return EFI_INVALID_PARAMETER;
}
//
// We only support BootPolicy == TRUE
//
if (!BootPolicy) {
DEBUG ((EFI_D_WARN, "\nLoadFile() BootPolicy == FALSE"));
return EFI_UNSUPPORTED;
}
//
// Get pointer to LoadFile protocol structure.
//
LoadfilePtr = CR (This, LOADFILE_DEVICE, LoadFile, LOADFILE_DEVICE_SIGNATURE);
if (LoadfilePtr == NULL) {
DEBUG (
(EFI_D_NET,
"\nLoadFile() Could not get pointer to LoadFile structure")
);
return EFI_INVALID_PARAMETER;
}
//
// Lock interface
//
EfiAcquireLock (&LoadfilePtr->Lock);
//
// Set console output mode and display attribute
//
if (OrigMode != 0) {
gST->ConOut->SetMode (gST->ConOut, 0);
}
gST->ConOut->SetAttribute (
gST->ConOut,
EFI_TEXT_ATTR (EFI_LIGHTGRAY,EFI_BLACK)
);
//
// See if BaseCode already has a Callback protocol attached.
// If there is none, attach our own Callback protocol.
//
Status = gBS->HandleProtocol (
LoadfilePtr->Private->Handle,
&gEfiPxeBaseCodeCallbackProtocolGuid,
(VOID *) &LoadfilePtr->Private->CallbackProtocolPtr
);
switch (Status) {
case EFI_SUCCESS:
//
// There is already a callback routine. Do nothing.
//
DEBUG ((EFI_D_WARN, "\nLoadFile() BC callback exists."));
break;
case EFI_UNSUPPORTED:
//
// No BaseCode Callback protocol found. Add our own.
//
Status = gBS->InstallProtocolInterface (
&LoadfilePtr->Private->Handle,
&gEfiPxeBaseCodeCallbackProtocolGuid,
EFI_NATIVE_INTERFACE,
&_bc_callback
);
DEBUG ((EFI_D_WARN, "\nLoadFile() Callback install status == %xh", Status));
RemoveCallback = (BOOLEAN) (Status == EFI_SUCCESS);
if (LoadfilePtr->Private->EfiBc.Mode != NULL && LoadfilePtr->Private->EfiBc.Mode->Started) {
NewMakeCallback = TRUE;
LoadfilePtr->Private->EfiBc.SetParameters (
&LoadfilePtr->Private->EfiBc,
NULL,
NULL,
NULL,
NULL,
&NewMakeCallback
);
}
break;
default:
DEBUG ((EFI_D_WARN, "\nLoadFile() Callback check status == %xh", Status));
}
//
// Check for starting or for continuing after already getting
// the file size.
//
if (LoadfilePtr->Private->FileSize == 0) {
TmpBufSz = 0;
Status = LoadfileStart (LoadfilePtr->Private, &TmpBufSz, Buffer);
if (sizeof (UINTN) < sizeof (UINT64) && TmpBufSz > 0xFFFFFFFF) {
*BufferSize = 0xFFFFFFFF;
} else {
*BufferSize = (UINTN) TmpBufSz;
}
if (Status == EFI_BUFFER_TOO_SMALL) {
//
// This is done so loadfile will work even if the boot manager
// did not make the first call with Buffer == NULL.
//
Buffer = NULL;
}
} else if (Buffer == NULL) {
DEBUG ((EFI_D_WARN, "\nLoadfile() Get buffer size"));
//
// Continuing from previous LoadFile request. Make sure there
// is a buffer and that it is big enough.
//
*BufferSize = LoadfilePtr->Private->FileSize;
Status = EFI_BUFFER_TOO_SMALL;
} else {
DEBUG ((EFI_D_WARN, "\nLoadFile() Download file"));
//
// Everything looks good, try to download the file.
//
TmpBufSz = *BufferSize;
Status = DownloadFile (LoadfilePtr->Private, &TmpBufSz, Buffer);
//
// Next call to loadfile will start DHCP process again.
//
LoadfilePtr->Private->FileSize = 0;
}
//
// If we added a callback protocol, now is the time to remove it.
//
if (RemoveCallback) {
NewMakeCallback = FALSE;
TempStatus = LoadfilePtr->Private->EfiBc.SetParameters (
&LoadfilePtr->Private->EfiBc,
NULL,
NULL,
NULL,
NULL,
&NewMakeCallback
);
if (TempStatus == EFI_SUCCESS) {
gBS->UninstallProtocolInterface (
LoadfilePtr->Private->Handle,
&gEfiPxeBaseCodeCallbackProtocolGuid,
&_bc_callback
);
}
}
//
// Restore display mode and attribute
//
if (OrigMode != 0) {
gST->ConOut->SetMode (gST->ConOut, OrigMode);
}
gST->ConOut->SetAttribute (gST->ConOut, OrigAttribute);
//
// Unlock interface
//
EfiReleaseLock (&LoadfilePtr->Lock);
DEBUG ((EFI_D_WARN, "\nBC.Loadfile() Status == %xh\n", Status));
switch (Status) {
case EFI_SUCCESS: /* 0 */
return EFI_SUCCESS;
case EFI_BUFFER_TOO_SMALL: /* 5 */
//
// Error is only displayed when we are actually trying to
// download the boot image.
//
if (Buffer == NULL) {
return EFI_BUFFER_TOO_SMALL;
}
Aprint ("\nPXE-E05: Download buffer is smaller than requested file.\n");
break;
case EFI_DEVICE_ERROR: /* 7 */
Aprint ("\nPXE-E07: Network device error. Check network connection.\n");
break;
case EFI_OUT_OF_RESOURCES: /* 9 */
Aprint ("\nPXE-E09: Could not allocate I/O buffers.\n");
break;
case EFI_NO_MEDIA: /* 12 */
Aprint ("\nPXE-E12: Could not detect network connection. Check cable.\n");
break;
case EFI_NO_RESPONSE: /* 16 */
Aprint ("\nPXE-E16: Valid PXE offer not received.\n");
break;
case EFI_TIMEOUT: /* 18 */
Aprint ("\nPXE-E18: Timeout. Server did not respond.\n");
break;
case EFI_ABORTED: /* 21 */
Aprint ("\nPXE-E21: Remote boot cancelled.\n");
break;
case EFI_ICMP_ERROR: /* 22 */
Aprint ("\nPXE-E22: Client received ICMP error from server.\n");
if (LoadfilePtr->Private->EfiBc.Mode == NULL) {
break;
}
if (!LoadfilePtr->Private->EfiBc.Mode->IcmpErrorReceived) {
break;
}
Aprint (
"PXE-E98: Type: %xh Code: %xh ",
LoadfilePtr->Private->EfiBc.Mode->IcmpError.Type,
LoadfilePtr->Private->EfiBc.Mode->IcmpError.Code
);
switch (LoadfilePtr->Private->EfiBc.Mode->IcmpError.Type) {
case 0x03:
switch (LoadfilePtr->Private->EfiBc.Mode->IcmpError.Code) {
case 0x00: /* net unreachable */
Aprint ("Net unreachable");
break;
case 0x01: /* host unreachable */
Aprint ("Host unreachable");
break;
case 0x02: /* protocol unreachable */
Aprint ("Protocol unreachable");
break;
case 0x03: /* port unreachable */
Aprint ("Port unreachable");
break;
case 0x04: /* Fragmentation needed */
Aprint ("Fragmentation needed");
break;
case 0x05: /* Source route failed */
Aprint ("Source route failed");
break;
}
break;
}
Aprint ("\n");
break;
case EFI_TFTP_ERROR: /* 23 */
Aprint ("\nPXE-E23: Client received TFTP error from server.\n");
if (LoadfilePtr->Private->EfiBc.Mode == NULL) {
break;
}
if (LoadfilePtr->Private->EfiBc.Mode->TftpErrorReceived) {
Aprint (
"PXE-E98: Code: %xh %a\n",
LoadfilePtr->Private->EfiBc.Mode->TftpError.ErrorCode,
LoadfilePtr->Private->EfiBc.Mode->TftpError.ErrorString
);
}
break;
default:
Aprint ("\nPXE-E99: Unexpected network error: %xh\n", Status);
}
LoadfilePtr->Private->EfiBc.Stop (&LoadfilePtr->Private->EfiBc);
return Status;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?