diff --git a/drivers/dw3/dw3.c b/drivers/dw3/dw3.c index 7ae4d8d..a64ee0b 100644 --- a/drivers/dw3/dw3.c +++ b/drivers/dw3/dw3.c @@ -831,7 +831,7 @@ _usb_init_xdci(EFI_USB_DEVICE_MODE_PROTOCOL *This) PCI_BUS(pci_dev), PCI_SLOT(pci_dev), PCI_FUNC(pci_dev)); config_params.BaseAddress = (UINTN)pci_read_bar64(pci_dev); - ewdbg("xDCI BaseAddress =0x%llx\n", (uint64_t)config_params.BaseAddress); + ewdbg("xDCI BaseAddress =0x%" PRIx64 "\n", (uint64_t)config_params.BaseAddress); /* configure xDCI as a system bus master */ pci_command = pci_read_config32(pci_dev, PCI_COMMAND); @@ -845,7 +845,7 @@ _usb_init_xdci(EFI_USB_DEVICE_MODE_PROTOCOL *This) PCI_BUS(pci_dev), PCI_SLOT(pci_dev), PCI_FUNC(pci_dev)); addr_hci = (UINTN)pci_read_bar64(pci_dev); - ewdbg("xHCI BaseAddress =0x%llx\n", (uint64_t)addr_hci); + ewdbg("xHCI BaseAddress =0x%" PRIx64 "\n", (uint64_t)addr_hci); /* enable xHCI bus master and I/O access */ pci_command = pci_read_config32(pci_dev, PCI_COMMAND); diff --git a/drivers/gop/gop.c b/drivers/gop/gop.c index 4710b54..0b047ba 100644 --- a/drivers/gop/gop.c +++ b/drivers/gop/gop.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Intel Corporation + * Copyright (c) 2018-2020, Intel Corporation * All rights reserved. * * Authors: Jérémy Compostella @@ -96,7 +96,7 @@ query_mode(EFI_GRAPHICS_OUTPUT_PROTOCOL *This, static void get_resolution(pcidev_t dev, UINT32 *width, UINT32 *height, size_t *pipe) { - uint32_t mmio, size; + unsigned long mmio, size; size_t i; mmio = pci_read_config32(dev, 0x10) & ~0xf; @@ -114,7 +114,7 @@ static void get_resolution(pcidev_t dev, UINT32 *width, UINT32 *height, static uint8_t *get_framebuffer(pcidev_t dev, size_t pipe) { - uint32_t mmio, gmaddr, surf; + unsigned long mmio, gmaddr, surf; mmio = pci_read_config32(dev, 0x10) & ~0xf; surf = read32((void *)(mmio + PLANE_SURF + pipe * PIPE_OFFSET)); @@ -125,7 +125,7 @@ static uint8_t *get_framebuffer(pcidev_t dev, size_t pipe) static void set_efi_color_order(pcidev_t dev) { - uint32_t mmio, ctl, surf; + unsigned long mmio, ctl, surf; size_t i; mmio = pci_read_config32(dev, 0x10) & ~0xf; @@ -251,6 +251,7 @@ static EFI_STATUS gop_init(EFI_SYSTEM_TABLE *st) }; pcidev_t pci_dev = 0; size_t i; + EFI_STATUS ret; if (!st) return EFI_INVALID_PARAMETER; @@ -277,9 +278,14 @@ static EFI_STATUS gop_init(EFI_SYSTEM_TABLE *st) if (!info.HorizontalResolution || !info.VerticalResolution) return EFI_SUCCESS; - return interface_init(st, &gop_guid, &gop_handle, - &gop_default, sizeof(gop_default), - (void **)&gop); + ret = interface_init(st, &gop_guid, &gop_handle, + &gop_default, sizeof(gop_default), + (void **)&gop); + if (EFI_ERROR(ret)) + return ret; + + set_mode((EFI_GRAPHICS_OUTPUT_PROTOCOL *)gop, 0); + return EFI_SUCCESS; } static EFI_STATUS gop_exit(EFI_SYSTEM_TABLE *st) diff --git a/drivers/heci/heci.c b/drivers/heci/heci.c index 7117310..e7a4c85 100644 --- a/drivers/heci/heci.c +++ b/drivers/heci/heci.c @@ -42,6 +42,7 @@ #include "ewlog.h" #include "heci_impl.h" #include "heci_protocol.h" +#include "heci2_protocol.h" #define UNUSED_PARAM __attribute__((__unused__)) @@ -49,6 +50,8 @@ #define HPET_BASE_ADDRESS 0xFED00000 #define ClockCycles() read32((void *)(HPET_BASE_ADDRESS + 0xf0)) +static EFI_HECI_PROTOCOL *heci; + static void init_timer(void) { uint32_t reg; @@ -574,9 +577,77 @@ static EFI_STATUS EFIAPI HeciSubmitCommand( return EFI_UNSUPPORTED; } +static EFIAPI EFI_STATUS +heci2_send_w_ack(UNUSED_PARAM HECI2_DEVICE HeciDev, + UINT32 *Message, + UINT32 Length, + UINT32 *RecLength, + UINT8 HostAddress, + UINT8 MEAddress) +{ + return heci->SendwACK(Message, Length, RecLength, HostAddress, MEAddress); +} + +static EFIAPI EFI_STATUS +heci2_read_msg(UNUSED_PARAM HECI2_DEVICE HeciDev, + UINT32 Blocking, + UINT32 *MessageBody, + UINT32 *Length) +{ + return heci->ReadMsg(Blocking, MessageBody, Length); +} + +static EFIAPI EFI_STATUS +heci2_send_msg(UNUSED_PARAM HECI2_DEVICE HeciDev, + UINT32 *Message, + UINT32 Length, + UINT8 HostAddress, + UINT8 MEAddress) +{ + return heci->SendMsg(Message, Length, HostAddress, MEAddress); +} + +static EFIAPI EFI_STATUS +heci2_reset_heci(UNUSED_PARAM HECI2_DEVICE HeciDev) +{ + return heci->ResetHeci(); +} + +static EFIAPI EFI_STATUS +heci2_init_heci(UNUSED_PARAM HECI2_DEVICE HeciDev) +{ + return heci->InitHeci(); +} + +static EFIAPI EFI_STATUS +heci2_me_reset_wait(UNUSED_PARAM HECI2_DEVICE HeciDev, + UINT32 Delay) +{ + return heci->SeCResetWait(Delay); +} + +static EFIAPI EFI_STATUS +heci2_re_init_heci(UNUSED_PARAM HECI2_DEVICE HeciDev) +{ + return heci->ReInitHeci(); +} + +static EFIAPI EFI_STATUS +heci2_get_me_status(UNUSED_PARAM UINT32 *Status) +{ + return heci->GetSeCStatus(Status); +} + +static EFIAPI EFI_STATUS +heci2_get_me_mode(UINT32 *Mode) +{ + return heci->GetSeCMode(Mode); +} static EFI_GUID heci_guid = HECI_PROTOCOL_GUID; static EFI_HANDLE handle; +static EFI_GUID heci2_guid = EFI_HECI2_PROTOCOL_GUID; +static EFI_HANDLE handle2; static EFI_STATUS heci_init(EFI_SYSTEM_TABLE * st) { @@ -594,11 +665,37 @@ static EFI_STATUS heci_init(EFI_SYSTEM_TABLE * st) .EnableSeCPG = HeciEnableSeCPG, .HeciSubmitCommand = HeciSubmitCommand, }; - EFI_HECI_PROTOCOL *heci_drv; + static struct EFI_HECI2_PROTOCOL_ heci2_default = { + .SendwACK = heci2_send_w_ack, + .ReadMsg = heci2_read_msg, + .SendMsg = heci2_send_msg, + .ResetHeci = heci2_reset_heci, + .InitHeci = heci2_init_heci, + .MeResetWait = heci2_me_reset_wait, + .ReInitHeci = heci2_re_init_heci, + .GetMeStatus = heci2_get_me_status, + .GetMeMode = heci2_get_me_mode + }; + EFI_STATUS ret; + EFI_HECI2_PROTOCOL *heci2_drv; + + ret = interface_init(st, &heci_guid, &handle, + &heci_default, sizeof(heci_default), + (void **)&heci); + if (EFI_ERROR(ret)) { + ewerr("Failed to register HECI protocol"); + return ret; + } + + ret = interface_init(st, &heci2_guid, &handle2, + &heci2_default, sizeof(heci2_default), + (void **)&heci2_drv); + if (EFI_ERROR(ret)) { + ewerr("Failed to register HECI2 protocol"); + interface_free(st, &heci_guid, handle); + } - return interface_init(st, &heci_guid, &handle, - &heci_default, sizeof(heci_default), - (void **)&heci_drv); + return ret; } static EFI_STATUS heci_exit(EFI_SYSTEM_TABLE * st) diff --git a/drivers/heci/heci2_protocol.h b/drivers/heci/heci2_protocol.h new file mode 100644 index 0000000..a3d477b --- /dev/null +++ b/drivers/heci/heci2_protocol.h @@ -0,0 +1,100 @@ +/** @file + This protocol provides services for HECI communucation. + See more details in https://github.com/intel/efiwrapper. + + Copyright (c) 2019, vit9696. All rights reserved.
+ Portions copyright 1999 - 2017 Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause +**/ + +#ifndef EFI_HECI2_H +#define EFI_HECI2_H + +#define EFI_HECI2_PROTOCOL_GUID \ + { 0x3C7BC880, 0x41F8, 0x4869, { 0xAE, 0xFC, 0x87, 0x0A, 0x3E, 0xD2, 0x82, 0x99 } } + +typedef UINT32 HECI2_DEVICE; +#define HECI_DEFAULT_DEVICE (0) + +typedef +EFI_STATUS +(EFIAPI *EFI_HECI2_SENDWACK) ( + IN HECI2_DEVICE HeciDev, + IN OUT UINT32 *Message, + IN OUT UINT32 Length, + IN OUT UINT32 *RecLength, + IN UINT8 HostAddress, + IN UINT8 MEAddress + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_HECI2_READ_MESSAGE) ( + IN HECI2_DEVICE HeciDev, + IN UINT32 Blocking, + IN UINT32 *MessageBody, + IN OUT UINT32 *Length + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_HECI2_SEND_MESSAGE) ( + IN HECI2_DEVICE HeciDev, + IN UINT32 *Message, + IN UINT32 Length, + IN UINT8 HostAddress, + IN UINT8 MEAddress + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_HECI2_RESET) ( + IN HECI2_DEVICE HeciDev + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_HECI2_INIT) ( + IN HECI2_DEVICE HeciDev + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_HECI2_REINIT) ( + IN HECI2_DEVICE HeciDev + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_HECI2_RESET_WAIT) ( + IN HECI2_DEVICE HeciDev, + IN UINT32 Delay + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_HECI2_GET_ME_STATUS) ( + OUT UINT32 *Status + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_HECI2_GET_ME_MODE) ( + OUT UINT32 *Mode + ); + +typedef struct EFI_HECI2_PROTOCOL_ { + EFI_HECI2_SENDWACK SendwACK; + EFI_HECI2_READ_MESSAGE ReadMsg; + EFI_HECI2_SEND_MESSAGE SendMsg; + EFI_HECI2_RESET ResetHeci; + EFI_HECI2_INIT InitHeci; + EFI_HECI2_RESET_WAIT MeResetWait; + EFI_HECI2_REINIT ReInitHeci; + EFI_HECI2_GET_ME_STATUS GetMeStatus; + EFI_HECI2_GET_ME_MODE GetMeMode; +} EFI_HECI2_PROTOCOL; + +extern EFI_GUID gEfiHeci2ProtocolGuid; + +#endif // EFI_HECI2_H diff --git a/drivers/lpkey/lpkey.c b/drivers/lpkey/lpkey.c new file mode 100644 index 0000000..8c78487 --- /dev/null +++ b/drivers/lpkey/lpkey.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2020, Intel Corporation + * All rights reserved. + * + * Author: Jérémy Compostella + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include + +#include "lpkey/lpkey.h" + +static EFI_CHECK_EVENT saved_check_event; +static EFI_EVENT wait_for_key; + +static EFIAPI EFI_STATUS +lpkey_check_event(EFI_EVENT Event) +{ + if (Event != wait_for_key) + return saved_check_event(Event); + + return havekey() ? EFI_SUCCESS : EFI_NOT_READY; +} + +static EFI_GUID guid = SIMPLE_TEXT_OUTPUT_PROTOCOL; + +static EFI_STATUS lpkey_init(EFI_SYSTEM_TABLE *st) +{ + EFI_STATUS ret; + SIMPLE_INPUT_INTERFACE *input; + + if (!st) + return EFI_INVALID_PARAMETER; + + ret = st->BootServices->LocateProtocol(&guid, NULL, (VOID **)&input); + if (EFI_ERROR(ret)) { + ewerr("Could not locate simple text input protocol"); + return ret; + } + + wait_for_key = input->WaitForKey; + saved_check_event = st->BootServices->CheckEvent; + st->BootServices->CheckEvent = lpkey_check_event; + + return EFI_SUCCESS; +} + + +static EFI_STATUS lpkey_exit(EFI_SYSTEM_TABLE *st) +{ + if (!st) + return EFI_INVALID_PARAMETER; + + st->BootServices->CheckEvent = saved_check_event; + + return EFI_SUCCESS; +} + +ewdrv_t lpkey_drv = { + .name = "lpkey", + .description = "Provide key event support based on libpayload havekey()", + .init = lpkey_init, + .exit = lpkey_exit +}; + diff --git a/drivers/lpkey/lpkey.h b/drivers/lpkey/lpkey.h new file mode 100644 index 0000000..b933e13 --- /dev/null +++ b/drivers/lpkey/lpkey.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2020, Intel Corporation + * All rights reserved. + * + * Author: Jérémy Compostella + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LPKEY_H_ +#define _LPKEY_H_ + +#include + +extern ewdrv_t lpkey_drv; + +#endif /* _LPKEY_H_ */ diff --git a/drivers/lpmemmap/lpmemmap.c b/drivers/lpmemmap/lpmemmap.c index ed23833..e87e91b 100644 --- a/drivers/lpmemmap/lpmemmap.c +++ b/drivers/lpmemmap/lpmemmap.c @@ -226,8 +226,7 @@ get_memory_map(UINTN *MemoryMapSize, EFI_MEMORY_DESCRIPTOR *MemoryMap, UINT32 key; UINTN size; - if (!MemoryMapSize || !MemoryMap || !MapKey || - !DescriptorSize || !DescriptorVersion) + if (!MemoryMapSize) return EFI_INVALID_PARAMETER; if (!efimemmap_nb || !efimemmap) @@ -239,15 +238,21 @@ get_memory_map(UINTN *MemoryMapSize, EFI_MEMORY_DESCRIPTOR *MemoryMap, return EFI_BUFFER_TOO_SMALL; } - ret = uefi_call_wrapper(crc32, 3, efimemmap, size, &key); - if (EFI_ERROR(ret)) - return ret; + if (MapKey) { + ret = uefi_call_wrapper(crc32, 3, efimemmap, size, &key); + if (EFI_ERROR(ret)) + return ret; + + *MapKey = key; + } *MemoryMapSize = size; - memcpy(MemoryMap, efimemmap, size); - *MapKey = key; - *DescriptorSize = sizeof(*efimemmap); - *DescriptorVersion = EFI_MEMORY_DESCRIPTOR_VERSION; + if (MemoryMap) + memcpy(MemoryMap, efimemmap, size); + if (DescriptorSize) + *DescriptorSize = sizeof(*efimemmap); + if (DescriptorVersion) + *DescriptorVersion = EFI_MEMORY_DESCRIPTOR_VERSION; return EFI_SUCCESS; } diff --git a/drivers/lppci/PciRootBridgeIo.h b/drivers/lppci/PciRootBridgeIo.h new file mode 100644 index 0000000..651519e --- /dev/null +++ b/drivers/lppci/PciRootBridgeIo.h @@ -0,0 +1,433 @@ +/** @file + PCI Root Bridge I/O protocol as defined in the UEFI 2.0 specification. + + PCI Root Bridge I/O protocol is used by PCI Bus Driver to perform PCI Memory, PCI I/O, + and PCI Configuration cycles on a PCI Root Bridge. It also provides services to perform + defferent types of bus mastering DMA. + + Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PCI_ROOT_BRIDGE_IO_H__ +#define __PCI_ROOT_BRIDGE_IO_H__ + +#define EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID \ + { \ + 0x2f707ebb, 0x4a1a, 0x11d4, {0x9a, 0x38, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + +typedef struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL; + +/// +/// ******************************************************* +/// EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH +/// ******************************************************* +/// +typedef enum { + EfiPciWidthUint8, + EfiPciWidthUint16, + EfiPciWidthUint32, + EfiPciWidthUint64, + EfiPciWidthFifoUint8, + EfiPciWidthFifoUint16, + EfiPciWidthFifoUint32, + EfiPciWidthFifoUint64, + EfiPciWidthFillUint8, + EfiPciWidthFillUint16, + EfiPciWidthFillUint32, + EfiPciWidthFillUint64, + EfiPciWidthMaximum +} EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH; + +/// +/// ******************************************************* +/// EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION +/// ******************************************************* +/// +typedef enum { + /// + /// A read operation from system memory by a bus master that is not capable of producing + /// PCI dual address cycles. + /// + EfiPciOperationBusMasterRead, + /// + /// A write operation from system memory by a bus master that is not capable of producing + /// PCI dual address cycles. + /// + EfiPciOperationBusMasterWrite, + /// + /// Provides both read and write access to system memory by both the processor and a bus + /// master that is not capable of producing PCI dual address cycles. + /// + EfiPciOperationBusMasterCommonBuffer, + /// + /// A read operation from system memory by a bus master that is capable of producing PCI + /// dual address cycles. + /// + EfiPciOperationBusMasterRead64, + /// + /// A write operation to system memory by a bus master that is capable of producing PCI + /// dual address cycles. + /// + EfiPciOperationBusMasterWrite64, + /// + /// Provides both read and write access to system memory by both the processor and a bus + /// master that is capable of producing PCI dual address cycles. + /// + EfiPciOperationBusMasterCommonBuffer64, + EfiPciOperationMaximum +} EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION; + +#define EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO 0x0001 +#define EFI_PCI_ATTRIBUTE_ISA_IO 0x0002 +#define EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO 0x0004 +#define EFI_PCI_ATTRIBUTE_VGA_MEMORY 0x0008 +#define EFI_PCI_ATTRIBUTE_VGA_IO 0x0010 +#define EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO 0x0020 +#define EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO 0x0040 +#define EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE 0x0080 +#define EFI_PCI_ATTRIBUTE_MEMORY_CACHED 0x0800 +#define EFI_PCI_ATTRIBUTE_MEMORY_DISABLE 0x1000 +#define EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE 0x8000 +#define EFI_PCI_ATTRIBUTE_ISA_IO_16 0x10000 +#define EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16 0x20000 +#define EFI_PCI_ATTRIBUTE_VGA_IO_16 0x40000 + +#define EFI_PCI_ATTRIBUTE_VALID_FOR_ALLOCATE_BUFFER (EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_PCI_ATTRIBUTE_MEMORY_CACHED | EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE) + +#define EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER (~EFI_PCI_ATTRIBUTE_VALID_FOR_ALLOCATE_BUFFER) + +typedef struct { + UINT8 Register; + UINT8 Function; + UINT8 Device; + UINT8 Bus; + UINT32 ExtendedRegister; +} EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS; + +/** + Reads from the I/O space of a PCI Root Bridge. Returns when either the polling exit criteria is + satisfied or after a defined duration. + + @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param Width Signifies the width of the memory or I/O operations. + @param Address The base address of the memory or I/O operations. + @param Mask Mask used for the polling criteria. + @param Value The comparison value used for the polling exit criteria. + @param Delay The number of 100 ns units to poll. + @param Result Pointer to the last value read from the memory location. + + @retval EFI_SUCCESS The last data returned from the access matched the poll exit criteria. + @retval EFI_TIMEOUT Delay expired before a match occurred. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_POLL_IO_MEM)( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINT64 Mask, + IN UINT64 Value, + IN UINT64 Delay, + OUT UINT64 *Result + ); + +/** + Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space. + + @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param Width Signifies the width of the memory operations. + @param Address The base address of the memory operations. + @param Count The number of memory operations to perform. + @param Buffer For read operations, the destination buffer to store the results. For write + operations, the source buffer to write data from. + + @retval EFI_SUCCESS The data was read from or written to the PCI root bridge. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_IO_MEM)( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ); + +typedef struct { + /// + /// Read PCI controller registers in the PCI root bridge memory space. + /// + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_IO_MEM Read; + /// + /// Write PCI controller registers in the PCI root bridge memory space. + /// + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_IO_MEM Write; +} EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS; + +/** + Enables a PCI driver to copy one region of PCI root bridge memory space to another region of PCI + root bridge memory space. + + @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance. + @param Width Signifies the width of the memory operations. + @param DestAddress The destination address of the memory operation. + @param SrcAddress The source address of the memory operation. + @param Count The number of memory operations to perform. + + @retval EFI_SUCCESS The data was copied from one memory region to another memory region. + @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_COPY_MEM)( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 DestAddress, + IN UINT64 SrcAddress, + IN UINTN Count + ); + +/** + Provides the PCI controller-specific addresses required to access system memory from a + DMA bus master. + + @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param Operation Indicates if the bus master is going to read or write to system memory. + @param HostAddress The system memory address to map to the PCI controller. + @param NumberOfBytes On input the number of bytes to map. On output the number of bytes + that were mapped. + @param DeviceAddress The resulting map address for the bus master PCI controller to use to + access the hosts HostAddress. + @param Mapping A resulting value to pass to Unmap(). + + @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes. + @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval EFI_DEVICE_ERROR The system hardware could not map the requested address. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_MAP)( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ); + +/** + Completes the Map() operation and releases any corresponding resources. + + @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param Mapping The mapping value returned from Map(). + + @retval EFI_SUCCESS The range was unmapped. + @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map(). + @retval EFI_DEVICE_ERROR The data was not committed to the target system memory. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_UNMAP)( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN VOID *Mapping + ); + +/** + Allocates pages that are suitable for an EfiPciOperationBusMasterCommonBuffer or + EfiPciOperationBusMasterCommonBuffer64 mapping. + + @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param Type This parameter is not used and must be ignored. + @param MemoryType The type of memory to allocate, EfiBootServicesData or + EfiRuntimeServicesData. + @param Pages The number of pages to allocate. + @param HostAddress A pointer to store the base system memory address of the + allocated range. + @param Attributes The requested bit mask of attributes for the allocated range. + + @retval EFI_SUCCESS The requested memory pages were allocated. + @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are + MEMORY_WRITE_COMBINE and MEMORY_CACHED. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ALLOCATE_BUFFER)( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + IN OUT VOID **HostAddress, + IN UINT64 Attributes + ); + +/** + Frees memory that was allocated with AllocateBuffer(). + + @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param Pages The number of pages to free. + @param HostAddress The base system memory address of the allocated range. + + @retval EFI_SUCCESS The requested memory pages were freed. + @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages + was not allocated with AllocateBuffer(). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_FREE_BUFFER)( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN UINTN Pages, + IN VOID *HostAddress + ); + +/** + Flushes all PCI posted write transactions from a PCI host bridge to system memory. + + @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + + @retval EFI_SUCCESS The PCI posted write transactions were flushed from the PCI host + bridge to system memory. + @retval EFI_DEVICE_ERROR The PCI posted write transactions were not flushed from the PCI + host bridge due to a hardware error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_FLUSH)( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This + ); + +/** + Gets the attributes that a PCI root bridge supports setting with SetAttributes(), and the + attributes that a PCI root bridge is currently using. + + @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param Supports A pointer to the mask of attributes that this PCI root bridge supports + setting with SetAttributes(). + @param Attributes A pointer to the mask of attributes that this PCI root bridge is currently + using. + + @retval EFI_SUCCESS If Supports is not NULL, then the attributes that the PCI root + bridge supports is returned in Supports. If Attributes is + not NULL, then the attributes that the PCI root bridge is currently + using is returned in Attributes. + @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL. + + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GET_ATTRIBUTES)( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + OUT UINT64 *Supports, + OUT UINT64 *Attributes + ); + +/** + Sets attributes for a resource range on a PCI root bridge. + + @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param Attributes The mask of attributes to set. + @param ResourceBase A pointer to the base address of the resource range to be modified by the + attributes specified by Attributes. + @param ResourceLength A pointer to the length of the resource range to be modified by the + attributes specified by Attributes. + + @retval EFI_SUCCESS The set of attributes specified by Attributes for the resource + range specified by ResourceBase and ResourceLength + were set on the PCI root bridge, and the actual resource range is + returned in ResuourceBase and ResourceLength. + @retval EFI_UNSUPPORTED A bit is set in Attributes that is not supported by the PCI Root + Bridge. + @retval EFI_OUT_OF_RESOURCES There are not enough resources to set the attributes on the + resource range specified by BaseAddress and Length. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_SET_ATTRIBUTES)( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN UINT64 Attributes, + IN OUT UINT64 *ResourceBase, + IN OUT UINT64 *ResourceLength + ); + +/** + Retrieves the current resource settings of this PCI root bridge in the form of a set of ACPI 2.0 + resource descriptors. + + @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param Resources A pointer to the ACPI 2.0 resource descriptors that describe the current + configuration of this PCI root bridge. + + @retval EFI_SUCCESS The current configuration of this PCI root bridge was returned in + Resources. + @retval EFI_UNSUPPORTED The current configuration of this PCI root bridge could not be + retrieved. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_CONFIGURATION)( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + OUT VOID **Resources + ); + +/// +/// Provides the basic Memory, I/O, PCI configuration, and DMA interfaces that are +/// used to abstract accesses to PCI controllers behind a PCI Root Bridge Controller. +/// +struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL { + /// + /// The EFI_HANDLE of the PCI Host Bridge of which this PCI Root Bridge is a member. + /// + EFI_HANDLE ParentHandle; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_POLL_IO_MEM PollMem; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_POLL_IO_MEM PollIo; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS Mem; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS Io; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS Pci; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_COPY_MEM CopyMem; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_MAP Map; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_UNMAP Unmap; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ALLOCATE_BUFFER AllocateBuffer; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_FREE_BUFFER FreeBuffer; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_FLUSH Flush; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GET_ATTRIBUTES GetAttributes; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_SET_ATTRIBUTES SetAttributes; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_CONFIGURATION Configuration; + + /// + /// The segment number that this PCI root bridge resides. + /// + UINT32 SegmentNumber; +}; + +extern EFI_GUID gEfiPciRootBridgeIoProtocolGuid; + +#endif diff --git a/drivers/lppci/lppci.c b/drivers/lppci/lppci.c new file mode 100644 index 0000000..5b83994 --- /dev/null +++ b/drivers/lppci/lppci.c @@ -0,0 +1,285 @@ +/* + * Copyright (c) 2020, Intel Corporation + * All rights reserved. + * + * Author: Jérémy Compostella + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include + +#include "lppci/lppci.h" +#include "lppci/PciRootBridgeIo.h" + +static EFIAPI EFI_STATUS +lppci_poll_mem(__attribute__((__unused__)) EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + __attribute__((__unused__)) EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + __attribute__((__unused__)) UINT64 Address, + __attribute__((__unused__)) UINT64 Mask, + __attribute__((__unused__)) UINT64 Value, + __attribute__((__unused__)) UINT64 Delay, + __attribute__((__unused__)) UINT64 *Result) +{ + return EFI_UNSUPPORTED; +} + +static EFIAPI EFI_STATUS +lppci_poll_io(__attribute__((__unused__)) EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + __attribute__((__unused__)) EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + __attribute__((__unused__)) UINT64 Address, + __attribute__((__unused__)) UINT64 Mask, + __attribute__((__unused__)) UINT64 Value, + __attribute__((__unused__)) UINT64 Delay, + __attribute__((__unused__)) UINT64 *Result) +{ + return EFI_UNSUPPORTED; +} + +static EFIAPI EFI_STATUS +lppci_access_mem_read(__attribute__((__unused__)) EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + __attribute__((__unused__)) EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + __attribute__((__unused__)) UINT64 Address, + __attribute__((__unused__)) UINTN Count, + __attribute__((__unused__)) VOID *Buffer) +{ + return EFI_UNSUPPORTED; +} + +static EFIAPI EFI_STATUS +lppci_access_mem_write(__attribute__((__unused__)) EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + __attribute__((__unused__)) EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + __attribute__((__unused__)) UINT64 Address, + __attribute__((__unused__)) UINTN Count, + __attribute__((__unused__)) VOID *Buffer) +{ + return EFI_UNSUPPORTED; +} + +static EFIAPI EFI_STATUS +lppci_access_io_read(__attribute__((__unused__)) EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + __attribute__((__unused__)) EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + __attribute__((__unused__)) UINT64 Address, + __attribute__((__unused__)) UINTN Count, + __attribute__((__unused__)) VOID *Buffer) +{ + return EFI_UNSUPPORTED; +} + +static EFIAPI EFI_STATUS +lppci_access_io_write(__attribute__((__unused__)) EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + __attribute__((__unused__)) EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + __attribute__((__unused__)) UINT64 Address, + __attribute__((__unused__)) UINTN Count, + __attribute__((__unused__)) VOID *Buffer) +{ + return EFI_UNSUPPORTED; +} + +static EFIAPI EFI_STATUS +lppci_access_pci_read(__attribute__((__unused__)) EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + UINT64 Address, + UINTN Count, + VOID *Buffer) +{ + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *addr; + pcidev_t dev; + UINTN i; + uint16_t reg; + + addr = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *)&Address; + dev = PCI_DEV(addr->Bus, addr->Device, addr->Function); + reg = addr->Register; + + for (i = 0; i < Count; i++) { + switch (Width) { + case EfiPciWidthUint8: + ((uint8_t *)Buffer)[i] = pci_read_config8(dev, addr->Register); + reg++; + break; + + case EfiPciWidthUint16: + ((uint16_t *)Buffer)[i] = pci_read_config16(dev, addr->Register); + reg += 2; + break; + + case EfiPciWidthUint32: + ((uint32_t *)Buffer)[i] = pci_read_config32(dev, addr->Register); + reg += 4; + break; + + default: + ewerr("pci read width %d is not supported", Width); + return EFI_UNSUPPORTED; + } + } + + return EFI_SUCCESS; +} + +static EFIAPI EFI_STATUS +lppci_access_pci_write(__attribute__((__unused__)) EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + __attribute__((__unused__)) EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + __attribute__((__unused__)) UINT64 Address, + __attribute__((__unused__)) UINTN Count, + __attribute__((__unused__)) VOID *Buffer) +{ + return EFI_UNSUPPORTED; +} + +static EFIAPI EFI_STATUS +lppci_copy_mem(__attribute__((__unused__)) EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + __attribute__((__unused__)) EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + __attribute__((__unused__)) UINT64 DestAddress, + __attribute__((__unused__)) UINT64 SrcAddress, + __attribute__((__unused__)) UINTN Count) +{ + return EFI_UNSUPPORTED; +} + +static EFIAPI EFI_STATUS +lppci_map(__attribute__((__unused__)) EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + __attribute__((__unused__)) EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation, + __attribute__((__unused__)) VOID *HostAddress, + __attribute__((__unused__)) UINTN *NumberOfBytes, + __attribute__((__unused__)) EFI_PHYSICAL_ADDRESS *DeviceAddress, + __attribute__((__unused__)) VOID **Mapping) +{ + return EFI_UNSUPPORTED; +} + +static EFIAPI EFI_STATUS +lppci_unmap(__attribute__((__unused__)) EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + __attribute__((__unused__)) VOID *Mapping) +{ + return EFI_UNSUPPORTED; +} + +static EFIAPI EFI_STATUS +lppci_allocate_buffer(__attribute__((__unused__)) EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + __attribute__((__unused__)) EFI_ALLOCATE_TYPE Type, + __attribute__((__unused__)) EFI_MEMORY_TYPE MemoryType, + __attribute__((__unused__)) UINTN Pages, + __attribute__((__unused__)) VOID **HostAddress, + __attribute__((__unused__)) UINT64 Attributes) +{ + return EFI_UNSUPPORTED; +} + +static EFIAPI EFI_STATUS +lppci_free_buffer(__attribute__((__unused__)) EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + __attribute__((__unused__)) UINTN Pages, + __attribute__((__unused__)) VOID *HostAddress) +{ + return EFI_UNSUPPORTED; +} + +static EFIAPI EFI_STATUS +lppci_flush(__attribute__((__unused__)) EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This) +{ + return EFI_UNSUPPORTED; +} + +static EFIAPI EFI_STATUS +lppci_get_attributes(__attribute__((__unused__)) EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + __attribute__((__unused__)) UINT64 *Supports, + __attribute__((__unused__)) UINT64 *Attributes) +{ + return EFI_UNSUPPORTED; +} + +static EFIAPI EFI_STATUS +lppci_set_attributes(__attribute__((__unused__)) EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + __attribute__((__unused__)) UINT64 Attributes, + __attribute__((__unused__)) UINT64 *ResourceBase, + __attribute__((__unused__)) UINT64 *ResourceLength) +{ + return EFI_UNSUPPORTED; +} + + +static EFIAPI EFI_STATUS +lppci_configuration(__attribute__((__unused__)) EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + __attribute__((__unused__)) VOID **Resources) +{ + return EFI_UNSUPPORTED; +} + +static EFI_GUID guid = EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID; +static EFI_HANDLE handle; + +static EFI_STATUS lppci_init(EFI_SYSTEM_TABLE *st) +{ + static EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL pciroot_default = { + .PollMem = lppci_poll_mem, + .PollIo = lppci_poll_io, + .Mem = { + .Read = lppci_access_mem_read, + .Write = lppci_access_mem_write + }, + .Io = { + .Read = lppci_access_io_read, + .Write = lppci_access_io_write + }, + .Pci = { + .Read = lppci_access_pci_read, + .Write = lppci_access_pci_write + }, + .CopyMem = lppci_copy_mem, + .Map = lppci_map, + .Unmap = lppci_unmap, + .AllocateBuffer = lppci_allocate_buffer, + .FreeBuffer = lppci_free_buffer, + .Flush = lppci_flush, + .GetAttributes = lppci_get_attributes, + .SetAttributes = lppci_set_attributes, + .Configuration = lppci_configuration + }; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *pciroot; + + if (!st) + return EFI_INVALID_PARAMETER; + + return interface_init(st, &guid, &handle, &pciroot_default, + sizeof(pciroot_default), (void **)&pciroot); +} + +static EFI_STATUS lppci_exit(EFI_SYSTEM_TABLE *st) +{ + return interface_free(st, &guid, handle); +} + +ewdrv_t lppci_drv = { + .name = "lppci", + .description = "PCI Root Bridge IO Protocol", + .init = lppci_init, + .exit = lppci_exit +}; + diff --git a/drivers/lppci/lppci.h b/drivers/lppci/lppci.h new file mode 100644 index 0000000..eefceea --- /dev/null +++ b/drivers/lppci/lppci.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2020, Intel Corporation + * All rights reserved. + * + * Author: Jérémy Compostella + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LPPCI_H_ +#define _LPPCI_H_ + +#include + +extern ewdrv_t lppci_drv; + +#endif /* _LPPCI_H_ */ diff --git a/drivers/sdhci_mmc/sdhci.c b/drivers/sdhci_mmc/sdhci.c index e3e74f4..11dd886 100644 --- a/drivers/sdhci_mmc/sdhci.c +++ b/drivers/sdhci_mmc/sdhci.c @@ -62,11 +62,10 @@ static void sdhci_reset_tuning(struct sdhci *host) sdhci_write16(host, SDHCI_HOST_CTRL2, ctrl); } -static int sdhci_abort_tuning(struct sdhci *host) +static void sdhci_abort_tuning(struct sdhci *host) { struct cmd tuning_cmd = {0}; struct cmd wait_cmd; - int ret; sdhci_write32(host, SDHCI_INT_ENABLE, SDHCI_INT_DATA_AVAIL); sdhci_write32(host, SDHCI_SIGNAL_ENABLE, SDHCI_INT_DATA_AVAIL); @@ -77,18 +76,14 @@ static int sdhci_abort_tuning(struct sdhci *host) tuning_cmd.flags |= CMDF_DATA_XFER | CMDF_USE_DMA; tuning_cmd.flags |= CMDF_WR_XFER; - ret = mmc_send_cmd(&tuning_cmd); - if (ret) - return EFI_DEVICE_ERROR; + mmc_send_cmd(&tuning_cmd); memset(&wait_cmd, 0, sizeof(wait_cmd)); wait_cmd.flags = CMDF_DATA_XFER; - ret = mmc_wait_cmd_done(&wait_cmd); - - return EFI_SUCCESS; + mmc_wait_cmd_done(&wait_cmd); } -static int sdhci_send_tuning(struct sdhci *host, uint32_t opcode) +static EFI_STATUS sdhci_send_tuning(struct sdhci *host, uint32_t opcode) { struct cmd tuning_cmd = {0}; uint32_t buf[256]={0}; @@ -130,7 +125,7 @@ static int sdhci_send_tuning(struct sdhci *host, uint32_t opcode) return EFI_NOT_READY; } -static int sdhci_execute_tuning(struct mmc *m) +static EFI_STATUS sdhci_execute_tuning(struct mmc *m) { struct sdhci *host = m->host; uint32_t ier1; @@ -138,7 +133,7 @@ static int sdhci_execute_tuning(struct mmc *m) uint16_t ctrl = 0; int counter; int ret = 0; - int err = 0; + EFI_STATUS err = 0; ier1 = sdhci_read32(host, SDHCI_INT_ENABLE); ier2 = sdhci_read32(host, SDHCI_SIGNAL_ENABLE); diff --git a/drivers/sdhci_mmc/sdhci.h b/drivers/sdhci_mmc/sdhci.h index 5de1906..dd05919 100644 --- a/drivers/sdhci_mmc/sdhci.h +++ b/drivers/sdhci_mmc/sdhci.h @@ -53,7 +53,7 @@ struct sdhci int (*wait_boot_done)(struct mmc *m, uintptr_t *dma_addr); void (*boot_stop)(struct mmc *m); int (*set_mode)(struct mmc *m); - int (*execute_tuning)(struct mmc *m); + EFI_STATUS (*execute_tuning)(struct mmc *m); uint32_t caps1; uint32_t caps2; diff --git a/host/Makefile b/host/Makefile index cbd9327..c60600d 100644 --- a/host/Makefile +++ b/host/Makefile @@ -9,8 +9,6 @@ OBJS := main.o \ tcp4.o \ fileio.o \ gop.o \ - image.o \ - pe.o \ host_time.o \ terminal_conin.o diff --git a/host/main.c b/host/main.c index 8423731..db6139d 100644 --- a/host/main.c +++ b/host/main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Intel Corporation + * Copyright (c) 2016-2020, Intel Corporation * All rights reserved. * * Author: Jérémy Compostella @@ -54,7 +54,6 @@ #include "tcp4.h" #include "fileio.h" #include "gop.h" -#include "image.h" #include "host_time.h" #include "terminal_conin.h" @@ -64,7 +63,6 @@ static ewdrv_t *host_drivers[] = { &tcp4_drv, &fileio_drv, &gop_drv, - &image_drv, &time_drv, &terminal_conin_drv, NULL diff --git a/include/libefiwrapper/external.h b/include/libefiwrapper/external.h index c6381dc..d4fd07c 100644 --- a/include/libefiwrapper/external.h +++ b/include/libefiwrapper/external.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Intel Corporation + * Copyright (c) 2016-2020, Intel Corporation * All rights reserved. * * Author: Jérémy Compostella @@ -61,6 +61,9 @@ long int strtol(const char *s, char **nptr, int base); unsigned long long int strtoull(const char *ptr, char **endptr, int base); long atol(const char *nptr); +/* malloc.h */ +void *memalign(size_t align, size_t size); + /* string.h */ int memcmp(const void *s1, const void *s2, size_t n); void *memcpy(void *dest, const void *src, size_t n); @@ -74,6 +77,8 @@ int strncmp(const char *s1, const char *s2, size_t n); /* stdio.h */ int printf(const char *format, ...); int snprintf(char *str, size_t size, const char *fmt, ...); +int getchar(void); +int putchar(unsigned int i); /* libpayload.h */ void ndelay(unsigned int n); diff --git a/libefiwrapper/Android.mk b/libefiwrapper/Android.mk index 271b8d5..226ac25 100644 --- a/libefiwrapper/Android.mk +++ b/libefiwrapper/Android.mk @@ -22,7 +22,9 @@ LIBEFIWRAPPER_SRC_FILES := \ ewarg.c \ sdio.c \ ewlib.c \ - eraseblk.c + eraseblk.c \ + image.c \ + pe.c include $(CLEAR_VARS) LOCAL_MODULE := libefiwrapper-$(TARGET_BUILD_VARIANT) diff --git a/libefiwrapper/Makefile b/libefiwrapper/Makefile index 8f624fb..9c931bd 100644 --- a/libefiwrapper/Makefile +++ b/libefiwrapper/Makefile @@ -24,7 +24,10 @@ OBJS := ewvar.o \ ewacpi.o \ ewarg.o \ sdio.o \ - ewlib.o + ewlib.o \ + eraseblk.o \ + image.o \ + pe.o $(EW_LIB): $(OBJS) $(AR) rcs $@ $^ diff --git a/libefiwrapper/conin.c b/libefiwrapper/conin.c index b808ec0..ce3e6cb 100644 --- a/libefiwrapper/conin.c +++ b/libefiwrapper/conin.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Intel Corporation + * Copyright (c) 2016-2020, Intel Corporation * All rights reserved. * * Author: Jérémy Compostella @@ -41,9 +41,10 @@ conin_reset(__attribute__((__unused__)) struct _SIMPLE_INPUT_INTERFACE *This, static EFIAPI EFI_STATUS conin_read_key(__attribute__((__unused__)) struct _SIMPLE_INPUT_INTERFACE *This, - __attribute__((__unused__)) EFI_INPUT_KEY *Key) + EFI_INPUT_KEY *Key) { - return EFI_NOT_FOUND; + Key->UnicodeChar = getchar(); + return EFI_SUCCESS; } static EFI_GUID guid = SIMPLE_TEXT_OUTPUT_PROTOCOL; @@ -52,7 +53,8 @@ EFI_STATUS conin_init(EFI_SYSTEM_TABLE *st) { static SIMPLE_INPUT_INTERFACE conin_default = { .Reset = conin_reset, - .ReadKeyStroke = conin_read_key + .ReadKeyStroke = conin_read_key, + .WaitForKey = (EFI_HANDLE)conin_init }; if (!st) diff --git a/libefiwrapper/conout.c b/libefiwrapper/conout.c index fd668c7..c26bb22 100644 --- a/libefiwrapper/conout.c +++ b/libefiwrapper/conout.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Intel Corporation + * Copyright (c) 2016-2020, Intel Corporation * All rights reserved. * * Author: Jérémy Compostella @@ -34,9 +34,12 @@ #include "lib.h" static EFIAPI EFI_STATUS -conout_reset(__attribute__((__unused__)) struct _SIMPLE_TEXT_OUTPUT_INTERFACE *This, +conout_reset(struct _SIMPLE_TEXT_OUTPUT_INTERFACE *This, __attribute__((__unused__)) BOOLEAN ExtendedVerification) { + This->SetCursorPosition(This, 0, 0); + This->ClearScreen(This); + This->EnableCursor(This, FALSE); return EFI_SUCCESS; } @@ -45,7 +48,7 @@ conout_output_string(__attribute__((__unused__)) struct _SIMPLE_TEXT_OUTPUT_INTE CHAR16 *String) { while (*String) - printf("%c", *String++); + putchar(*String++); return EFI_SUCCESS; } @@ -59,46 +62,93 @@ conout_test_string(__attribute__((__unused__)) struct _SIMPLE_TEXT_OUTPUT_INTERF static EFIAPI EFI_STATUS conout_query_mode(__attribute__((__unused__)) struct _SIMPLE_TEXT_OUTPUT_INTERFACE *This, - __attribute__((__unused__)) UINTN ModeNumber, - __attribute__((__unused__)) UINTN *Columns, - __attribute__((__unused__)) UINTN *Rows) + UINTN ModeNumber, + UINTN *Columns, + UINTN *Rows) { - return EFI_UNSUPPORTED; + if (ModeNumber) + return EFI_UNSUPPORTED; + + *Columns = 80; + *Rows = 25; + + return EFI_SUCCESS; } static EFIAPI EFI_STATUS conout_set_mode(__attribute__((__unused__)) struct _SIMPLE_TEXT_OUTPUT_INTERFACE *This, - __attribute__((__unused__)) UINTN ModeNumber) + UINTN ModeNumber) { - return EFI_UNSUPPORTED; + return ModeNumber ? EFI_UNSUPPORTED : EFI_SUCCESS; } static EFIAPI EFI_STATUS conout_set_attribute(__attribute__((__unused__)) struct _SIMPLE_TEXT_OUTPUT_INTERFACE *This, - __attribute__((__unused__)) UINTN Attribute) + UINTN Attribute) { - return EFI_UNSUPPORTED; + static const int FOREGROUND_COLOR[] = { + [EFI_BLACK] = 30, + [EFI_BLUE] = 34, + [EFI_GREEN] = 32, + [EFI_CYAN] = 36, + [EFI_RED] = 31, + [EFI_MAGENTA] = 35, + [EFI_BROWN] = 37, /* Default to white */ + [EFI_LIGHTGRAY] = 90, + [EFI_BRIGHT] = 37, /* Default to white */ + [EFI_LIGHTBLUE] = 94, + [EFI_LIGHTGREEN] = 92, + [EFI_LIGHTCYAN] = 96, + [EFI_LIGHTRED] = 91, + [EFI_LIGHTMAGENTA] = 95, + [EFI_YELLOW] = 33, + [EFI_WHITE] = 37 + }; + + static const int BACKGROUND_COLOR[] = { + [EFI_BACKGROUND_BLACK >> 4] = 40, + [EFI_BACKGROUND_BLUE >> 4] = 44, + [EFI_BACKGROUND_GREEN >> 4] = 42, + [EFI_BACKGROUND_CYAN >> 4] = 46, + [EFI_BACKGROUND_RED >> 4] = 41, + [EFI_BACKGROUND_MAGENTA >> 4] = 45, + [EFI_BACKGROUND_BROWN >> 4] = 40, /* Default to black */ + [EFI_BACKGROUND_LIGHTGRAY >> 4] = 47, + }; + + if (Attribute == 0x0) { + printf("\e[0m"); + return EFI_SUCCESS; + } + + printf("\e[%d;%dm", FOREGROUND_COLOR[Attribute & 0xF], + BACKGROUND_COLOR[(Attribute >> 4) & 0x7]); + + return EFI_SUCCESS; } static EFIAPI EFI_STATUS conout_clear_screen(__attribute__((__unused__)) struct _SIMPLE_TEXT_OUTPUT_INTERFACE *This) { - return EFI_UNSUPPORTED; + printf("\e[2J"); + return EFI_SUCCESS; } static EFIAPI EFI_STATUS conout_set_cursor_position(__attribute__((__unused__)) struct _SIMPLE_TEXT_OUTPUT_INTERFACE *This, - __attribute__((__unused__)) UINTN Column, - __attribute__((__unused__)) UINTN Row) + UINTN Column, + UINTN Row) { - return EFI_UNSUPPORTED; + printf("\e[%zd;%zdH", Row + 1, Column + 1); + return EFI_SUCCESS; } static EFIAPI EFI_STATUS conout_enable_cursor(__attribute__((__unused__)) struct _SIMPLE_TEXT_OUTPUT_INTERFACE *This, - __attribute__((__unused__)) BOOLEAN Enable) + BOOLEAN Enable) { - return EFI_UNSUPPORTED; + printf(Enable ? "\e[?25h" : "\e[?25l"); + return EFI_SUCCESS; } static SIMPLE_TEXT_OUTPUT_MODE mode; diff --git a/libefiwrapper/core.c b/libefiwrapper/core.c index 7d1ebda..adce472 100644 --- a/libefiwrapper/core.c +++ b/libefiwrapper/core.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Intel Corporation + * Copyright (c) 2016-2020, Intel Corporation * All rights reserved. * * Author: Jérémy Compostella @@ -35,6 +35,7 @@ #include "ewarg.h" #include "ewlog.h" #include "ewvar.h" +#include "image.h" #include "lib.h" #include "rs.h" #include "serialio.h" @@ -90,7 +91,8 @@ static struct component { { "console in", conin_init, conin_free }, { "console out", conout_init, conout_free }, { "serial", serialio_init, serialio_free }, - { "smbios", smbios_init, smbios_free } + { "smbios", smbios_init, smbios_free }, + { "image", image_init, image_free } }; EFI_STATUS set_load_options(int argc, char **argv) diff --git a/libefiwrapper/ewacpi.c b/libefiwrapper/ewacpi.c index ee79970..488fd38 100644 --- a/libefiwrapper/ewacpi.c +++ b/libefiwrapper/ewacpi.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Intel Corporation + * Copyright (c) 2016-2020, Intel Corporation * All rights reserved. * * Author: Jérémy Compostella @@ -95,10 +95,10 @@ EFI_STATUS ewacpi_get_table(EFI_SYSTEM_TABLE *st, const char *name, if (!rsdp->xsdt_address) return EFI_UNSUPPORTED; - xsdt = (struct xsdt_table *)(UINTN)rsdp->xsdt_address; + xsdt = (struct xsdt_table *)(unsigned long)rsdp->xsdt_address; nb = (xsdt->header.length - sizeof(xsdt->header)) / sizeof(xsdt->entry); for (i = 0; i < nb; i++) { - cur = (struct acpi_header *)(UINTN)xsdt->entry[i]; + cur = (struct acpi_header *)(unsigned long)xsdt->entry[i]; if (memcmp(name, cur->signature, SIG_SIZE)) continue; ret = validate_table(cur); diff --git a/host/image.c b/libefiwrapper/image.c similarity index 94% rename from host/image.c rename to libefiwrapper/image.c index 4e7377f..ab497d7 100644 --- a/host/image.c +++ b/libefiwrapper/image.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Intel Corporation + * Copyright (c) 2016-2020, Intel Corporation * All rights reserved. * * Author: Jérémy Compostella @@ -83,7 +83,9 @@ start_image(EFI_HANDLE ImageHandle, { EFI_STATUS ret; image_t *image; +#if defined(HOST) int setjmpret; +#endif if (ExitDataSize || ExitData) return EFI_UNSUPPORTED; @@ -92,9 +94,11 @@ start_image(EFI_HANDLE ImageHandle, if (EFI_ERROR(ret)) return ret; +#if defined(HOST) setjmpret = setjmp(image->jmp); if (setjmpret != 0) return image->exit_status; +#endif return image->entry(ImageHandle, saved_st); } @@ -116,8 +120,9 @@ efi_exit(EFI_HANDLE ImageHandle, return ret; image->exit_status = ExitStatus; +#if defined(HOST) longjmp(image->jmp, 1); - +#endif return EFI_SUCCESS; } @@ -141,7 +146,7 @@ static EFI_IMAGE_START saved_start_image; static EFI_EXIT saved_efi_exit; static EFI_IMAGE_UNLOAD saved_unload_image; -static EFI_STATUS image_init(EFI_SYSTEM_TABLE *st) +EFI_STATUS image_init(EFI_SYSTEM_TABLE *st) { if (!st) return EFI_INVALID_PARAMETER; @@ -161,7 +166,7 @@ static EFI_STATUS image_init(EFI_SYSTEM_TABLE *st) return EFI_SUCCESS; } -static EFI_STATUS image_exit(EFI_SYSTEM_TABLE *st) +EFI_STATUS image_free(EFI_SYSTEM_TABLE *st) { if (!st) return EFI_INVALID_PARAMETER; @@ -173,10 +178,3 @@ static EFI_STATUS image_exit(EFI_SYSTEM_TABLE *st) return EFI_SUCCESS; } - -ewdrv_t image_drv = { - .name = "image", - .description = "PE/COFF image", - .init = image_init, - .exit = image_exit -}; diff --git a/host/image.h b/libefiwrapper/image.h similarity index 90% rename from host/image.h rename to libefiwrapper/image.h index 82c3627..9878bdf 100644 --- a/host/image.h +++ b/libefiwrapper/image.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Intel Corporation + * Copyright (c) 2016-2020, Intel Corporation * All rights reserved. * * Author: Jérémy Compostella @@ -32,17 +32,24 @@ #ifndef _IMAGE_H_ #define _IMAGE_H_ +#if defined(HOST) #include +#endif #include typedef struct image { EFI_LOADED_IMAGE prot; void *data; +#if defined(HOST) jmp_buf jmp; +#endif EFI_IMAGE_ENTRY_POINT entry; EFI_STATUS exit_status; } image_t; extern ewdrv_t image_drv; +EFI_STATUS image_init(EFI_SYSTEM_TABLE *st); +EFI_STATUS image_free(EFI_SYSTEM_TABLE *st); + #endif /* _IMAGE_H_ */ diff --git a/host/pe.c b/libefiwrapper/pe.c similarity index 72% rename from host/pe.c rename to libefiwrapper/pe.c index 942b246..3e4bea6 100644 --- a/host/pe.c +++ b/libefiwrapper/pe.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Intel Corporation + * Copyright (c) 2016-2020, Intel Corporation * All rights reserved. * * Author: Jérémy Compostella @@ -29,12 +29,16 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include +#include #include #include #include + +#if defined(HOST) #include +#endif +#include "lib.h" #include "pe.h" /* The following structure definitions come from: @@ -99,7 +103,7 @@ typedef struct { } std_coff_t; typedef struct { - UINTN image_base; + unsigned long image_base; UINT32 section_alignment; UINT32 file_alignment; UINT16 major_operating_system_version; @@ -114,20 +118,22 @@ typedef struct { UINT32 checksum; UINT16 subsystem; UINT16 dll_characteristics; - UINTN size_of_stack_reserve; - UINTN size_of_stack_commit; - UINTN size_of_heap_reserve; - UINTN size_of_heap_commit; + unsigned long size_of_stack_reserve; + unsigned long size_of_stack_commit; + unsigned long size_of_heap_reserve; + unsigned long size_of_heap_commit; UINT32 loader_flags; UINT32 number_of_rva_and_sizes; } win_t; +#define BASERELOC_DIRECTORY_ENTRY 5 + typedef struct { coff_header_t hdr; struct { std_coff_t std; win_t win; - struct { + struct data_directory { UINT32 address; UINT32 size; } data_directory[16]; @@ -147,6 +153,30 @@ typedef struct { UINT32 characteristics; } section_header_t; +typedef struct { + UINT32 virtual_address; + UINT32 size_of_block; +} relocation_t; + +typedef enum { + ABSOLUTE, + HIGH, + LOW, + HIGHLOW, + HIGHADJ, + MACHINE_SPECIFIC_5, + RESERVED, + MACHINE_SPECIFIC_7, + MACHINE_SPECIFIC_8, + MACHINE_SPECIFIC_9, + DIR64 +} fixup_type_t; + +typedef struct { + UINT16 offset: 12; + UINT8 type: 4; +} fixup_t; + #pragma pack() typedef struct { @@ -156,8 +186,8 @@ typedef struct { UINT32 end; } loaded_section_t; -void get_section_boundaries(section_header_t *section, UINT16 nb, - UINT32 *start, UINT32 *end) +static void get_section_boundaries(section_header_t *section, UINT16 nb, + UINT32 *start, UINT32 *end) { UINT16 i; @@ -165,14 +195,17 @@ void get_section_boundaries(section_header_t *section, UINT16 nb, *end = 0; for (i = 0; i < nb; i++) { + UINT32 size = section[i].virtual_size; + if (section[i].size_of_raw_data) + size = section[i].size_of_raw_data; *start = min(*start, section[i].virtual_address); - *end = max(*end, section[i].virtual_address + - section[i].virtual_size); + *end = max(*end, section[i].virtual_address + size); } } -EFI_STATUS load_sections(section_header_t *section, UINT16 nb, - void *base, image_t *image) +static EFI_STATUS load_sections(section_header_t *section, UINT16 nb, + void *base, image_t *image, + size_t alignment, loaded_section_t **data_p) { loaded_section_t *data; UINT16 i; @@ -188,9 +221,13 @@ EFI_STATUS load_sections(section_header_t *section, UINT16 nb, get_section_boundaries(section, nb, &data->start, &data->end); data->size = data->end - data->start; +#if defined(HOST) data->addr = mmap(NULL, data->size, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0); - if (!data->addr) { +#else + data->addr = memalign(alignment, data->size); +#endif + if (data->addr == (void *) -1 || data->addr == NULL) { ewerr("Failed to allocate sections memory"); free(data); return EFI_OUT_OF_RESOURCES; @@ -205,7 +242,7 @@ EFI_STATUS load_sections(section_header_t *section, UINT16 nb, data->start; size = section[i].virtual_size; - if (!size && section[i].size_of_raw_data) + if (section[i].size_of_raw_data) size = section[i].size_of_raw_data; memcpy(dst, src, size); @@ -216,15 +253,49 @@ EFI_STATUS load_sections(section_header_t *section, UINT16 nb, ewdbg(".text section loaded at %p", dst); } + *data_p = data; return EFI_SUCCESS; } +static void relocate(loaded_section_t *data, unsigned long base, + relocation_t *table, UINT32 size) +{ + relocation_t *table_end = (relocation_t *)((UINT8 *)table + size); + unsigned long diff = (unsigned long)data->addr - base - data->start; + + while (table < table_end) { + fixup_t *fixup = (fixup_t *)&table[1]; + fixup_t *fixup_end = (fixup_t *)((char *)table + table->size_of_block); + unsigned char *mem = (unsigned char *)data->addr + + table->virtual_address - data->start; + + for (; fixup < fixup_end; fixup++) { + if (*(UINT16 *)fixup == 0) + break; + switch (fixup->type) { + case HIGHLOW: + *(UINT32 *)&mem[fixup->offset] += diff; + break; + case DIR64: + *(UINT64 *)&mem[fixup->offset] += diff; + break; + default: + ewerr("Unsupported relocation type %d", + fixup->type); + } + } + table = (relocation_t *)fixup_end; + } +} + EFI_STATUS pe_load(void *data, UINTN size, image_t *image) { EFI_STATUS ret; dos_header_t *dos_hdr; pe_coff_t *pe; char *entry; + loaded_section_t *section; + struct data_directory *reloc_dir; if (!data || !size || !image) return EFI_INVALID_PARAMETER; @@ -248,10 +319,16 @@ EFI_STATUS pe_load(void *data, UINTN size, image_t *image) ret = load_sections((section_header_t *)(pe + 1), pe->hdr.number_of_sections, - data, image); + data, image, pe->opt.win.section_alignment, + §ion); if (EFI_ERROR(ret)) return ret; + reloc_dir = &pe->opt.data_directory[BASERELOC_DIRECTORY_ENTRY]; + relocate((loaded_section_t *)image->data, pe->opt.win.image_base, + section->addr + reloc_dir->address - section->start, + reloc_dir->size); + entry = (char *)((loaded_section_t *)image->data)->addr; entry += pe->opt.std.address_of_entry_point; entry -= ((loaded_section_t *)image->data)->start; @@ -268,7 +345,11 @@ EFI_STATUS pe_unload(image_t *image) return EFI_INVALID_PARAMETER; data = image->data; +#if defined(HOST) munmap(data->addr, data->size); +#else + free(data->addr); +#endif free(data); image->data = NULL; diff --git a/host/pe.h b/libefiwrapper/pe.h similarity index 97% rename from host/pe.h rename to libefiwrapper/pe.h index 146211f..04848bf 100644 --- a/host/pe.h +++ b/libefiwrapper/pe.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Intel Corporation + * Copyright (c) 2016-2020, Intel Corporation * All rights reserved. * * Author: Jérémy Compostella diff --git a/libefiwrapper/protocol.c b/libefiwrapper/protocol.c index b24a6a4..5c75f6b 100644 --- a/libefiwrapper/protocol.c +++ b/libefiwrapper/protocol.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Intel Corporation + * Copyright (c) 2016-2020, Intel Corporation * All rights reserved. * * Author: Jérémy Compostella @@ -349,11 +349,26 @@ locate_handle_buffer(EFI_LOCATE_SEARCH_TYPE SearchType, } static EFIAPI EFI_STATUS -locate_protocol(__attribute__((__unused__)) EFI_GUID *Protocol, +locate_protocol(EFI_GUID *Protocol, __attribute__((__unused__)) VOID *Registration, - __attribute__((__unused__)) VOID **Interface) + VOID **Interface) { - return EFI_UNSUPPORTED; + interface_t *inte; + size_t i; + + if (!Interface) + return EFI_INVALID_PARAMETER; + + for (i = 0; i < ARRAY_SIZE(INTERFACES); i++) { + inte = &INTERFACES[i]; + if (inte->installed && + !guidcmp(&inte->protocol, Protocol)) { + *Interface = inte->interface; + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; } EFI_STATUS protocol_init_bs(EFI_BOOT_SERVICES *bs) diff --git a/libefiwrapper/serialio.c b/libefiwrapper/serialio.c index e356aec..4a814d9 100644 --- a/libefiwrapper/serialio.c +++ b/libefiwrapper/serialio.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Intel Corporation + * Copyright (c) 2016-2020, Intel Corporation * All rights reserved. * * Authors: Jérémy Compostella @@ -49,7 +49,7 @@ serialio_write(__attribute__((__unused__)) SERIAL_IO_INTERFACE *This, return EFI_INVALID_PARAMETER; for (i = 0; i < *BufferSize; i++) - printf("%c", ((char *)Buffer)[i]); + putchar(((unsigned char *)Buffer)[i]); return EFI_SUCCESS; } diff --git a/libefiwrapper/version.h b/libefiwrapper/version.h index 18a577c..45c6769 100644 --- a/libefiwrapper/version.h +++ b/libefiwrapper/version.h @@ -46,7 +46,7 @@ #define HEX(a) PASTE(0x, a) #define _EFIWRAPPER_MAJOR 03 -#define _EFIWRAPPER_MINOR 02 +#define _EFIWRAPPER_MINOR 03 #define EFIWRAPPER_MAJOR HEX(_EFIWRAPPER_MAJOR) #define EFIWRAPPER_MINOR HEX(_EFIWRAPPER_MINOR)