Fix MultiBoot image loading issue

The current MulitBoot loading code in SBL did not follow the specification.
The spec stated "The offset in the OS image file at which to start loading
is defined by the offset at which the header was found, minus
(header_addr - load_addr)". However, the current code always copies from
offset 0 of the image file. It caused exception when loading some valid
multiboot image.

Signed-off-by: Maurice Ma <maurice.ma@intel.com>
This commit is contained in:
Maurice Ma 2020-07-07 15:55:42 -07:00
parent 99e4ba268c
commit 48ca17769b
1 changed files with 23 additions and 16 deletions

View File

@ -1,7 +1,7 @@
/** @file /** @file
This file Multiboot specification (implementation). This file Multiboot specification (implementation).
Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR> Copyright (c) 2014 - 2020, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent SPDX-License-Identifier: BSD-2-Clause-Patent
**/ **/
@ -281,10 +281,14 @@ SetupMultibootImage (
) )
{ {
EFI_STATUS Status; EFI_STATUS Status;
UINT32 *LoadAddr; UINT8 *HeaderAddr;
UINT32 *LoadEnd; UINT8 *LoadAddr;
UINT32 *BssEnd; UINT8 *LoadEnd;
UINT8 *BssEnd;
CONST MULTIBOOT_HEADER *MbHeader; CONST MULTIBOOT_HEADER *MbHeader;
UINT8 *CopyStart;
UINT32 ImgOffset;
UINT32 ImgLength;
if (MultiBoot == NULL) { if (MultiBoot == NULL) {
return RETURN_INVALID_PARAMETER; return RETURN_INVALID_PARAMETER;
@ -307,18 +311,21 @@ SetupMultibootImage (
} }
} }
LoadAddr = MbHeader->LoadAddr; HeaderAddr = MbHeader->HeaderAddr;
LoadEnd = MbHeader->LoadEndAddr; LoadAddr = MbHeader->LoadAddr;
BssEnd = MbHeader->BssEndAddr; LoadEnd = MbHeader->LoadEndAddr;
DEBUG ((DEBUG_INFO, "Mb: LoadAddr=0x%p, LoadEnd=0x%p , BssEnd=0x%p\n", LoadAddr, LoadEnd, BssEnd)); BssEnd = MbHeader->BssEndAddr;
if (LoadEnd == NULL) { ImgOffset = (UINT32)((UINT8 *)MbHeader - (UINT8 *)MultiBoot->BootFile.Addr - (HeaderAddr - LoadAddr));
// zero means "load the entire file" ImgLength = (UINT32)((LoadEnd == NULL) ? MultiBoot->BootFile.Size - ImgOffset : LoadEnd - LoadAddr);
CopyMem (LoadAddr, (UINT8 * )MultiBoot->BootFile.Addr, MultiBoot->BootFile.Size); if ((ImgOffset >= MultiBoot->BootFile.Size) || (ImgOffset + ImgLength > MultiBoot->BootFile.Size)) {
DEBUG ((DEBUG_INFO, "Mb: copy image to 0x%p, Size=0x%x\n", LoadAddr, MultiBoot->BootFile.Size)); return RETURN_LOAD_ERROR;
} else { }
CopyMem (LoadAddr, MultiBoot->BootFile.Addr, sizeof (UINT32) * (LoadEnd - LoadAddr));
DEBUG ((DEBUG_INFO, "Mb: copy image to 0x%p, Size=0x%x\n", LoadAddr, sizeof (UINT32) * (LoadEnd - LoadAddr))); DEBUG ((DEBUG_INFO, "Mb: LoadAddr=0x%p, LoadEnd=0x%p , BssEnd=0x%p, Size=0x%x\n", LoadAddr, LoadEnd, BssEnd, ImgLength));
if ((UINT32)(UINTN)BssEnd != 0) { CopyStart = (UINT8 *)MultiBoot->BootFile.Addr + ImgOffset;
CopyMem (LoadAddr, CopyStart, ImgLength);
if ((BssEnd != NULL) && (LoadEnd != NULL)) {
if (BssEnd > LoadEnd) {
ZeroMem ((VOID *) LoadEnd, BssEnd - LoadEnd); ZeroMem ((VOID *) LoadEnd, BssEnd - LoadEnd);
} }
} }