/** Install PxeBaseCodeCallbackProtocol if not installed before. @param[in, out] Private Pointer to PxeBc private data. @param[out] NewMakeCallback If TRUE, it is a new callback. Otherwise, it is not new callback. @retval EFI_SUCCESS PxeBaseCodeCallbackProtocol installed succesfully. @retval Others Failed to install PxeBaseCodeCallbackProtocol. **/ EFI_STATUS PxeBcInstallCallback ( IN OUT PXEBC_PRIVATE_DATA *Private, OUT BOOLEAN *NewMakeCallback ) { EFI_PXE_BASE_CODE_PROTOCOL *PxeBc; EFI_STATUS Status; // // Check whether PxeBaseCodeCallbackProtocol already installed. // PxeBc = &Private->PxeBc; Status = gBS->HandleProtocol ( Private->Controller, &gEfiPxeBaseCodeCallbackProtocolGuid, (VOID **) &Private->PxeBcCallback ); if (Status == EFI_UNSUPPORTED) { CopyMem ( &Private->LoadFileCallback, &gPxeBcCallBackTemplate, sizeof (EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL) ); // // Install a default callback if user didn't offer one. // Status = gBS->InstallProtocolInterface ( &Private->Controller, &gEfiPxeBaseCodeCallbackProtocolGuid, EFI_NATIVE_INTERFACE, &Private->LoadFileCallback ); (*NewMakeCallback) = (BOOLEAN) (Status == EFI_SUCCESS); Status = PxeBc->SetParameters (PxeBc, NULL, NULL, NULL, NULL, NewMakeCallback); if (EFI_ERROR (Status)) { PxeBc->Stop (PxeBc); return Status; } } return EFI_SUCCESS; }
EFI_STATUS BdsPxeLoadImage ( IN OUT EFI_DEVICE_PATH **DevicePath, IN EFI_HANDLE Handle, IN EFI_DEVICE_PATH *RemainingDevicePath, IN EFI_ALLOCATE_TYPE Type, IN OUT EFI_PHYSICAL_ADDRESS* Image, OUT UINTN *ImageSize ) { EFI_STATUS Status; EFI_LOAD_FILE_PROTOCOL *LoadFileProtocol; UINTN BufferSize; EFI_PXE_BASE_CODE_PROTOCOL *Pxe; // Get Load File Protocol attached to the PXE protocol Status = gBS->HandleProtocol (Handle, &gEfiLoadFileProtocolGuid, (VOID **)&LoadFileProtocol); if (EFI_ERROR (Status)) { return Status; } Status = LoadFileProtocol->LoadFile (LoadFileProtocol, *DevicePath, TRUE, &BufferSize, NULL); if (Status == EFI_BUFFER_TOO_SMALL) { Status = gBS->AllocatePages (Type, EfiBootServicesCode, EFI_SIZE_TO_PAGES(BufferSize), Image); if (EFI_ERROR (Status)) { return Status; } Status = LoadFileProtocol->LoadFile (LoadFileProtocol, *DevicePath, TRUE, &BufferSize, (VOID*)(UINTN)(*Image)); if (!EFI_ERROR (Status) && (ImageSize != NULL)) { *ImageSize = BufferSize; } } if (Status == EFI_ALREADY_STARTED) { Status = gBS->LocateProtocol (&gEfiPxeBaseCodeProtocolGuid, NULL, (VOID **)&Pxe); if (!EFI_ERROR(Status)) { // If PXE is already started, we stop it Pxe->Stop (Pxe); // And we try again return BdsPxeLoadImage (DevicePath, Handle, RemainingDevicePath, Type, Image, ImageSize); } } return Status; }